Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Конструктор класса, поля и методы set, как правильно делать? 
:(
    Опции темы
thomas
Дата 10.10.2010, 18:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доцент... почти
***


Профиль
Группа: Завсегдатай
Сообщений: 1385
Регистрация: 3.10.2006
Где: " Сказочное королевство"

Репутация: нет
Всего: 65



Приветствую всех.
Прошу пояснить простой пример.
Создаю класс описывающий адрес.
Задаю четыре поля (к примеру):
индекс(int), город(String), улица(String), номер дома(int).
Пишу конструктор с четырмя параметрами и четыре пары методов get set (для каждого поля).
Так как я пришел в Яву с C#, то проверку данных прописал в методах set.
Например индекс должен быть в пределах от 1000 до 10000,
или для города/улицы не допускаеться пустое значение (если нет ввода, то присваиваеться дефолтное значение).
А в конструкторе класса просто вызываю методы set для полей.

Посмотрел что препод написал в решении. Там все по другому.
Проверка проводиться прямо в конструкторе, а в set методах ничего нет.
Код

// его вариант конструктора с проверкой почтового индекса
public Adres(String straatnaam, short huisnummer, String bus, int postcode,
            String woonplaats) {
        this.straatnaam = straatnaam;
        this.huisnummer = huisnummer;
        this.bus = bus;

        if (postcode > 999 && postcode < 10000)
            this.postcode = postcode;
        else
            this.postcode = 1000;
        this.woonplaats = woonplaats;

    }
//его вавриант методов
public int getPostcode() {
        return postcode;
    }

    public void setPostcode(int postcode) {
        this.postcode = postcode;
    }

А как по вашему правильно и почему?

Я написал так
Код

public int getPostcode(){
        return postcode;
    }    public void setPostcode(int postcode){
        if (postcode > 999 && postcode < 10000)
            this.postcode = postcode;
        else
            this.postcode = 1000;
    }
// и часть кода конструктора
public Adres(String straatnaam, short huisnummer, String bus, int postcode, String woonplaats){
        ...
        setPostcode(postcode);
        ...
    }

Заранее благодарю.


--------------------
Крепко жму горло, искренне ваш Thomas. (С)vingrad
Некоторые сорта флоры буквально за одно мгновение превращают нас в фауну!
Проблемы негров шерифа не волнуют.
PM MAIL   Вверх
Egik2
Дата 10.10.2010, 19:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 302
Регистрация: 29.7.2008
Где: Агудзера

Репутация: нет
Всего: 11



Из этих 2 вариантов, на мой взгляд более логичен твой вариант.
Ведь установка поля может проводиться и внутри конструктора и просто в методе set -поэтому для того чтобы логика работы с индексом была в одном месте граммотней все сделать в setе.
Однако я думаю поступил бы немного подругому.
Создал бы отдельный класс Index с одним private полем и конструктором и инкапсулировал в него всю логику работы с индексом.


--------------------
Три великие добродетели программиста: лень, нетерпение и самомнение (Larry Wall)
a-nav.com
developer-blog.ru
world-poetry.org
PM MAIL WWW ICQ   Вверх
powerOn
Дата 10.10.2010, 21:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 47
Всего: 159



Цитата(thomas @  10.10.2010,  19:07 Найти цитируемый пост)
Проверка проводиться прямо в конструкторе, а в set методах ничего нет.


очевидно, что это не правильно. другое дело, если бы сеттеров не было. получилось бы реализация шаблона immutable.


--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
thomas
Дата 10.10.2010, 22:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доцент... почти
***


Профиль
Группа: Завсегдатай
Сообщений: 1385
Регистрация: 3.10.2006
Где: " Сказочное королевство"

Репутация: нет
Всего: 65



Приветствую всех еще раз.

Значит, если я правильно понимаю, то:
- поля класса обьявляем приватными;
- проверку на валидность вводимых значений проводим в методах set;
- инициализацию полей класса производим в конструкторе, вызывая методы set.
Т.е. конструктор создает нам валидный обьект - экземпляр данного класса.

А вот методы set надо обьявлять закрытыми или открытыми?



--------------------
Крепко жму горло, искренне ваш Thomas. (С)vingrad
Некоторые сорта флоры буквально за одно мгновение превращают нас в фауну!
Проблемы негров шерифа не волнуют.
PM MAIL   Вверх
mstalker26
Дата 10.10.2010, 22:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 206
Регистрация: 4.7.2009

Репутация: 4
Всего: 11



Геттеры и сеттеры должны быть открытыми, как же иначе ты "достучишься" до них. Менять значения ты можешь (теоретически и практически) и после создания экземпляра класса.
--------------------
Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
PM   Вверх
thomas
Дата 16.10.2010, 17:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доцент... почти
***


Профиль
Группа: Завсегдатай
Сообщений: 1385
Регистрация: 3.10.2006
Где: " Сказочное королевство"

Репутация: нет
Всего: 65



Приветствую всех.

То что геттеры и сеттеры должны быть публичными, я понимаю. Это обеспечивает возможность запрашивать значения полей экзкмпляра класса и соответственно менять их.

Но вот что касается реализации конструктора, я не допонимаю.

Конструктор предназначен для создания экземпляра класса.
Конструктор по умолчанию и конструктор без параметров создают клас с дефолтными значениями полей.
Конструктор с параметрами создает экземпляр класса с заданными значениями полей.
И вот тут мне не совсем понятно. Естественно мы не можем подсунуть конструктору параметры не соответствующего типа.
Но вот подсунуть значения которые не удовлетворяют тем или иным условиям в принципе запросто.
Если в конструкторе просто инициировать поля класса, то мы можем получить "не правильный обьект" (экземпляр класса, значения полей которого не отвечают тем или иным условиям.) Значит в конструкторе надо писать код проверки. 
В принципе проверку соответствия значения поля заданным условиям мы обычно реализуем в сеттерах.
Получаеться дублирование кода. Что не есть хорошо.

Какой выход?
Вызывать в конструкторе сеттеры для полей класса?

Что есть правильно с точки зрения языка JAVA?

Заранее благодарю.


--------------------
Крепко жму горло, искренне ваш Thomas. (С)vingrad
Некоторые сорта флоры буквально за одно мгновение превращают нас в фауну!
Проблемы негров шерифа не волнуют.
PM MAIL   Вверх
wedens
Дата 17.10.2010, 09:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 17.10.2009

Репутация: нет
Всего: нет



во-первых никто не отменял Factory Method, проверяйте что угодно, кидайте исключения, на создании объекта не отразится. во-вторых есть такой паттерн как Builder.  а исключения в конструкторе имхо зло.

Это сообщение отредактировал(а) wedens - 17.10.2010, 11:56
PM MAIL   Вверх
Старовъръ
Дата 17.10.2010, 12:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 491
Регистрация: 8.5.2008

Репутация: 4
Всего: 10



Цитата
очевидно, что это не правильно. другое дело, если бы сеттеров не было. получилось бы реализация шаблона immutable. 
Ммм.. не уверен, что это можно назвать шаблоном, однако мне кажется это лучшее решение для класса Address. Такие объекты инициализируются лишь однажды и уже не изменяются как правило, поэтому я бы предложил сделать класс все-таки immutable (ТС, гугл поможет если не знаешь как). По-моему это самое правильное решение. Если же все-таки нужны set-методы и объект правда будет изменяться, то проверку логичней сделать в этих методах и вызывать их из конструктора (как ты и сделал, насколько я понимаю). 
Преподаватель однозначно неправ, т.к. объект выходит может содержать некорректные значения, установленные по срествам сеттеров.
Цитата
а исключения в конструкторе имхо зло.
Какая разница будет ли исключение выброшено в Фабрике или в конструкторе? Все равно объект не будет создан.
PM MAIL WWW   Вверх
thomas
Дата 25.10.2010, 21:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доцент... почти
***


Профиль
Группа: Завсегдатай
Сообщений: 1385
Регистрация: 3.10.2006
Где: " Сказочное королевство"

Репутация: нет
Всего: 65



Приветствую всех.
Наконец то сам разобралься что к чему.
Ларчик то просто открывался.
Исходя из принцыпов, что setter должен быть публичным, а конструкторы не могут содержать публичные методы и нужно проводить проверку значения поля перед присвоение на валидность, 
приходим к выводу, что нужно сделать приватный метод, проверяющий вводимые значения на валидность и вызывать его как из setter-а, так и из конструктора.

Всем спасибо за обсуждение.
Удачи и успехов во всем.

Это сообщение отредактировал(а) thomas - 25.10.2010, 23:46


--------------------
Крепко жму горло, искренне ваш Thomas. (С)vingrad
Некоторые сорта флоры буквально за одно мгновение превращают нас в фауну!
Проблемы негров шерифа не волнуют.
PM MAIL   Вверх
mantracoder
Дата 25.10.2010, 21:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 3.8.2007

Репутация: 1
Всего: 1



Ко всему вышесказанному хотелось бы добавить, что данные и логику лучше разделять. Данные и проверка данных - это, по сути, две большие разницы. Один и тот же объект может быть валидным в одной ситуации и не валидным в другой. Поэтому, я бы предложил вынести валидацию в отдельный объект-валидатор.
PM MAIL   Вверх
Старовъръ
Дата 25.10.2010, 22:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 491
Регистрация: 8.5.2008

Репутация: 4
Всего: 10



Цитата
Исходя из принцыпов, что setter должен быть публичным, а конструкторы не могут содержать публичные методы и нужно проводить проверку значения поля перед присвоение на валидность, приходим у выводу, что нужно сделать приватный метод, проверяющий вводимые значения на валидность и вызывать его как из setter-а, так и из конструктора.
Здравое решение, имеет место быть smile
Цитата
Ко всему вышесказанному хотелось бы добавить, что данные и логику лучше разделять. Данные и проверка данных - это, по сути, две большие разницы. Один и тот же объект может быть валидным в одной ситуации и не валидным в другой. Поэтому, я бы предложил вынести валидацию в отдельный объект-валидатор. 
Что приведет к полностью анемичной модели и усложнению приложения. Если объект создается для определенной системы и правила валидации будут всегда одинаковы (а в большинстве случаев такая валидация как длинна/величина поля являются неизменными), то лучше логику пихать именно в доменной модели.
PM MAIL WWW   Вверх
Sibit
Дата 26.10.2010, 04:50 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 96
Регистрация: 6.10.2009
Где: NSK

Репутация: нет
Всего: 1



Цитата

конструкторы не могут содержать публичные методы


Это конечно оффтопик, но мне интересно, а почему так? Иногда это использовал, но не думал, что так делать не стоит.

Это сообщение отредактировал(а) Sibit - 26.10.2010, 04:52
PM MAIL   Вверх
Старовъръ
Дата 26.10.2010, 07:51 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 491
Регистрация: 8.5.2008

Репутация: 4
Всего: 10



Делать так нельзя потому, что эти методы можно переопределить в классе-наследнике, в таком случае когда будет вызвать конструктор предка, а поля наследника еще не инициализированы, это может привести к печальным последствиям. Если методы вызываются из конструктора, их нужно делать или private, или final.
PM MAIL WWW   Вверх
Skipy
Дата 27.10.2010, 12:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 487
Регистрация: 24.8.2006
Где: Москва, Россия

Репутация: 6
Всего: 16



Цитата(Sibit @ 26.10.2010,  04:50)
Цитата

конструкторы не могут содержать публичные методы


Это конечно оффтопик, но мне интересно, а почему так? Иногда это использовал, но не думал, что так делать не стоит.

Уточню - конструкторы не должны вызывать методы класса, которые можно переопределить. Простой пример:

Код
package ru.skipy.tests;

/**
 * InheritanceTest
 *
 * @author Eugene Matyushkin
 * @since 11.10.2010
 */
public class InheritanceTest {

    static class A {
        private String string = "Green";

        public A (){
            System.out.println("String: \""+getString()+"\", length="+getString().length());
        }


        public String getString() {
            return string;
        }

        public void setString(String string) {
            this.string = string;
        }
    }

    static class B extends A{

        private String string = "red";

        public String getString() {
            return string;
        }

        public void setString(String string) {
            this.string = string;
        }
    }

    public static void main(String[] args) {
        try{
            B b = new B();
        }catch(Throwable th){
            System.out.println("Main exception: "+th);
        }
    }
}


Казалось бы - все просто. Метод getString() переопределен без подвохов. Однако запустите и посмотрите, что будет. А я потом расскажу, почему.


--------------------
С уважением,
Евгений aka Skipy
www.skipy.ru
PM MAIL WWW ICQ   Вверх
Sibit
Дата 28.10.2010, 06:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 96
Регистрация: 6.10.2009
Где: NSK

Репутация: нет
Всего: 1



Цитата

Однако запустите и посмотрите, что будет


Запустил, пишет Main exception: java.lang.NullPointerException  .

Скорей всего по тому, что при 
Код

System.out.println("String: \""+getString()+"\", length="+getString().length());


getString вызывается у класса B а у него поле string в этот момент еще не определено.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0645 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.