LINUX.ORG.RU
Ответ на: комментарий от qnikst

программа вываливается там, где она не должна. Это не правильно.

Если бы это случалось на этапе компиляции — ДА. Но это случается в рантайме из-за ошибки тупого программиста клиента, который передаёт а объект Квадрат НЕВЕРНЫЕ значения. Эта программная ошибка. И она никак не нарушает биобаланс иерархии наследования.

Всё, что работает с более высоким уровнем абстракции должно продолжать работать и при конкретизации.

Нисходящее приведение типа (например, объект класса Прямоугольник привести к классу Квадрат при условии, что класс Квадрат — дочерний от класса Прямоугольник) в ООП никто не обещал. При этом ведь получается, что дополнительная информация (дополнительные поля), приобретаемая объектом, неопределённа, следовательно, это лишено практического смысла:

Rectangle rec = new Rectangle(System.out);
Square sq = (Square)rect;
sq.refresh();
Exception in thread "main" java.lang.ClassCastException: devpackage.Rectangle cannot be cast to clientpackage.Square
	at clientpackage.FigureTest.main(FigureTest.java:30)

iZEN ★★★★★
()
Ответ на: комментарий от iZEN

> о это случается в рантайме из-за ошибки тупого программиста клиента, который передаёт а объект Квадрат НЕВЕРНЫЕ значения

потому-что ты быдлокодер и сделал для квадрата совершенно ненужный ему метод

lester ★★★★
()
Ответ на: комментарий от iZEN

iZEN, ты адекватен? То про принцип Лисков вещаешь, а то выдаёшь такие перлы выдаёшь.

Если функция работает с экземпляром класса, она должна работать и с наследниками. У тебя при работе с квадратом функция для прямоугольника может выдать IllegalStateException, функция, в которой не указаны Exception'ы, это нормально? (хотя есть подозрение, что на этапе компиляции умная явамашина тебе это объяснит)

Но это случается в рантайме из-за ошибки тупого программиста клиента, который передаёт а объект Квадрат НЕВЕРНЫЕ значения.

из-за ошибки тупого архитектора, который наследовал квадрат от прямоугольника <<- fix.

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

>Если функция работает с экземпляром класса, она должна работать и с наследниками.

Покажи где не работает. Посмотри ЧТО не работает — не работает вызов с заведомо неправильными параметрами — очевидная реакция на атаку правильно написанного библиотечного кода.

У тебя при работе с квадратом функция для прямоугольника может выдать IllegalStateException


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

функция, в которой не указаны Exception'ы, это нормально?


Вполне. Я предлагал внести её в контракт метода в виде проверяемого исключения, если ты не заметил.

(хотя есть подозрение, что на этапе компиляции умная явамашина тебе это объяснит)


Умная явамашина на этапе компиляции объясняет только проверяемые исключения, если их не так используют.

из-за ошибки тупого архитектора, который наследовал квадрат от прямоугольника <<- fix.


В том числе. Поэтому Джошуа Блох предпочитает компоновку вместо наследования. Иерархию наследования можно оптимально спроектировать только в границах пакета. Всё, что выходит за границы пакета, следует рассматривать как нарушение инкапсуляции (раскрытия деталей) класса. И геттеры этому способствуют ещё больше, но уже в объектах.
В противовес этому техника миксинов и компоновки лишь добавляет функциональность, не нарушая инкапсуляции.

iZEN ★★★★★
()
Ответ на: комментарий от lester

потому-что ты быдлокодер и сделал для квадрата совершенно ненужный ему метод

Для квадрата метод resize(int, int) ничего не несёт, кроме головной боли. Но в силу наследования от Rectangle, в котором реализуется интерфейс Resizeable, от этого метода больше не избавиться и в других наследуемых классах.

Чтобы решить проблему, нужно что-то сделать. И я это, по крайней мере, попытался сделать.

Такие глупые иерархии наследования встречаются сплошь и рядом — достаточно посмотреть исходники любой ООП-программы, написанной новичками.

iZEN ★★★★★
()
Ответ на: комментарий от jtootf

напомните-ка мне уважаемый, где я Вам обещал рабочий код?

вопросов больше не имею

слишком быстро сливаешься, не интересно даже

shty ★★★★★
()
Ответ на: комментарий от iZEN

в общем я обещал tailgunner'у код. попытаюсь расписать поподробнее и код и примеры, почему квадрат->прямоугольник это плохо и так _лучше_ не делать и почему прямоугольник->квадрат, это не правильно и так делать _нельзя_.

Умная явамашина на этапе компиляции объясняет только проверяемые исключения, если их не так используют.

это тоже проверим :) ты походу просто не догоняешь, где проблема ^_^

Иерархию наследования можно оптимально спроектировать только в границах пакета. Всё, что выходит за границы пакета, следует рассматривать как нарушение инкапсуляции (раскрытия деталей) класса.

разработчики библиотек даже не смотрят на тебя ^_^

Выложу код и текст как приеду домой, подозреваю, что в районе 21.00MSK.

В противовес этому техника миксинов и компоновки лишь добавляет функциональность, не нарушая инкапсуляции.

То, что существуют другие подходы, а не только ООП это ясно, вопрос в том, насколько они оправданы и когда они оправданы.

qnikst ★★★★★
()
Ответ на: комментарий от iZEN

> Чтобы решить проблему, нужно что-то сделать. И я это, по крайней мере, попытался сделать.

не наследовать от Rectangle и не доказывать, что это правильно. //К.О.

qnikst ★★★★★
()
Ответ на: комментарий от iZEN

> Для квадрата метод resize(int, int) ничего не несёт, кроме головной боли. Но в силу наследования от Rectangle

вывод - это наследование лишнее

в котором реализуется интерфейс Resizeable


интерфейс в текущем виде с реализацией в виде броска исключения на ровном месте не походит для решения задачи, т.к. код, который работает только с Resizeable, ничего не знает об ограничениях, и потому бросок такого исключения будет в том месте и неожиданным и непонятным, а значит надо использовать другие методы - например CanFit + Fit + BestFit, и на месте использования уже можно будет спрашивать у объекта сможет ли он занять всю площадь, или частично, или вообще не сможет, и отображать это все, например, на экране

lester ★★★★
()
Ответ на: комментарий от lester

и да - это все не мешает иметь у Rectangle и Square метод resize, например, у каждого свой, которыми смогут пользоваться те, кто работает именно с этими классами, а не с Resizeable

lester ★★★★
()
Ответ на: комментарий от qnikst

>не наследовать от Rectangle и не доказывать, что это правильно. //К.О.

«А поговорить?» © Ж))

iZEN ★★★★★
()
Ответ на: комментарий от tailgunner

пока мне не удалось сделать _хороший_ вариант демонстрации проблемы с реализацией get4Parts() на java в силу того, что generics там такой generics, что данный код не заработает :(. Или код будет таким, что явно видна подгонка под желаемый результат. Однако

 
 import java.io.PrintStream;

public class main3 {

    public static void main(String [] args) {
        Rectangle3 r = new Rectangle3(System.out);
        Square3 s    = new Square3(System.out);
        r.resize(5,5);
        Solver<Rectangle3> slv1 = new Solver<Rectangle3>(r); 
        slv1.solve(1.0);
        s.resize(5,5);
        Solver<Square3> slv2 = new Solver<Square3>(s); 
        slv2.solve(1.0);
    }

}

class Solver<T extends Rectangle3> {

    final T area;

    public Solver(T area){
        this.area = area;
    }

    public double solve(double time){
        int oldWidth = area.getWidth();
        int oldHeight = area.getHeight();
        double result;
        synchronized(area){
            area.resize(oldWidth, oldHeight/2 );
            result = area.solve(time);
            area.resize(oldWidth,oldHeight);
        }
        return result;
    }

}

вместо того, чтобы успешно отработать вернёт следующее:

 Rectangle solve Exception in thread "main" java.lang.IllegalStateException: ааааа! 

это значит, что код который должен был отработать, а из-за дополнительных ограничений (о которых никто не может знать) программа вылетела. Самое забавное будет в случае, если такая ошибка вылезет не где-то наверху, а в глубине большой библиотеки. И использующему её придётся рефакторить свой код. Или писать костыли типа временных врапперов Square в rectangle бросающих исключение при попытке привести их обратно к square.

Если таки придумаю ещё пример приведу. Однако здесь данные слова скорее напонимают К.О. и в общем-то никому не нужны походу ;)

qnikst ★★★★★
()
Ответ на: комментарий от no-dashi

>> Давай ты не будешь прятаться за ынтерпрайз-баззвордами.

Давай ты пойдешь и попробуешь усвоить тот простой факт, что сохранение объекта в базе может идти в фоновом режиме

То есть, возвращаясь к примеру http://www.linux.org.ru/jump-message.jsp?msgid=4708731&cid=4713188 , ответ звучит так: «Message не извлекается из Queue, потому что может возникнуть нужда сохранять Message в фоновом режиме, и эту задачу я решил возложить на Queue»?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Message не извлекается из Queue, потому что может возникнуть нужда сохранять Message в фоновом режиме, и эту задачу я решил возложить на Queue"?

*ять, Message это не привычное тебе «сообщение», которое можно «извлечь из очереди и работать с ним», это объект с дительных жизненным циклом (от нескольких минут), с которым одновременно работают несколько потоков. И Queue в данном случае циклическая очередь «грязных» объектов - достали из начала, поместили в конец. И объект становится «грязным» (изменяется) в течение секунды с предыдущего сохранения с вероятностью 0.5

no-dashi ★★★★★
()
Ответ на: комментарий от qnikst

Учи матчасть

java.lang.IllegalStateException бросается, если в многопоточном приложении два и более потока пытаются работать с неправильно заблокированным (synchronized) объектом.

iZEN ★★★★★
()
Ответ на: Учи матчасть от iZEN

да ладно тебе, тот оно стояло по мотивам этого, ибо описывает кривизну работы твоего класса, а автор того кода сам знаешь кто ;)

по поводу твоего определения IllegalStateException

/*

* Signals that a method has been invoked at an illegal or

* inappropriate time. In other words, the Java environment or

* Java application is not in an appropriate state for the requested

* operation.

*/

интересно почему меня мучают сомнения, что твоё определение не верное, во всяком случае оно точно неполное :)

учим матчасть оба?

P.S. по поводу наследования прямоугольник->квадрат дискуссия всё ещё идёт?

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

по поводу наследования прямоугольник->квадрат дискуссия всё ещё идёт?

Нет. Дискуссия исчерпала себя. Но мы выяснили, что наследование порочно, так как не всё однозначно с наследованием контрактов.

iZEN ★★★★★
()
Ответ на: комментарий от iZEN

если ты пояснишь к чему ты это сказал, то я возможно смогу что-нибудь ответить :)

qnikst ★★★★★
()
Ответ на: комментарий от iZEN

> Нет. Дискуссия исчерпала себя.

ok

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

какое-то больно фанатичное заявление. ну да ладно, подожду следующего открытия подобной темы, тем более, что они раз в 1-2 недели появляются.

qnikst ★★★★★
()
Ответ на: комментарий от iZEN

> Но мы выяснили, что наследование порочно

в неумелых руках людей, которые думают задом-наперед - не от задачи к решению, а от решения к задаче

lester ★★★★
()
Ответ на: комментарий от no-dashi

> Message это не привычное тебе «сообщение»,

Ты не знаешь, к чему я привык.

которое можно «извлечь из очереди и работать с ним», это объект с дительных жизненным циклом (от нескольких минут)

Мониторы - уж точно не единственный способ проектировать многонитевые приложения.

которым одновременно работают несколько потоков. И Queue в данном случае циклическая очередь «грязных» объектов - достали из начала, поместили в конец.

Это ты так спроектировал систему (или в учебнике посмотрел - не суть важно). Но можно проектировать и по-другому.

tailgunner ★★★★★
()

Такой мегасрач, и лишь из-за ограниченности Java. Если бы в Java классах можно было использовать свойства, как в C#, этой темы не было бы.

    class Address
    {
        protected string city;
        protected string zipCode;

        public string ZipCode
        {
            get
            {
                return zipCode;
            }
            set
            {
                // Validate value against some datastore.
                zipCode = value;
                // Update city based on validated zipCode.
            }
        }
    }

Пример взят отсюда: http://www.microsoft.com/mspress/books/sampchap/5027a.aspx

bbk123 ★★★★★
()
Ответ на: комментарий от bbk123

a). разговор о сях был

б). выделять С-решётка не обязательно, не только там properties есть

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

qnikst ★★★★★
()
Ответ на: комментарий от lester

>в неумелых руках людей, которые думают задом-наперед - не от задачи к решению, а от решения к задаче

есть подозрение, что вот это:

параллелограмм->прямоугольник->квадрат

параллелограмм->ромб->квадрат

прямоугольник != ромб (если это не квадрат)

именно наследованием классов изменяемых объектов не отразить. Т.е. либо просто работаем с параллелограммами, но в каждый момент можем определить - является ли наш объект (соответствует определению) ромбом/квадратом/и т.д.(полиморфизм и прочее идут в зад, всё должно быть описано один раз и навсегда), либо таки делаем объекты неизменяемыми, и на каждый чих рождаем новый (умной proxy?), а он в зависимости от заданных параметром будет одним из... Или есть третий путь?

Да, нахуа нам фигуры - не спрашивайте, будем считать, что без них - никак =)

yyk ★★★★★
()
Ответ на: комментарий от yyk

>именно наследованием классов изменяемых объектов не отразить.

Именно.

man Образцы проектирования

1) State
2) Strategy

— паттерны описывают свойства изменчивости объекта и следуют идеологии КОМПОЗИЦИИ.

iZEN ★★★★★
()

А как это «проще»?

Переменные класса ВСЕГДА должны быть private.

«One basic principle of OO systems is data abstraction. You should completely hide the way in which an object implements a message handler from the rest of the program. That's one reason why all of your instance variables (a class's nonconstant fields) should be private.» (c)

Bioreactor ★★★★★
()
Ответ на: комментарий от bbk123

> из-за ограниченности Java

Приведенный код показывает нечитабельность и перегруженность лишними сущностями шарпея, а не «органиченность» Джавы.

Потому как шарпей - это эклектичная смесь С++ и Выжуал Барсика, где Label1.Caption (нынче Label1.Text) - это тяжелое наследие VB <= 6.0, VBScript и VBA, где объекты не создавались изначально в коде, а только пользовались готовые объекты, напейсанные на COM в C++.

Bioreactor ★★★★★
()
Ответ на: комментарий от yyk

Вы совершенно верно поставили квантор общности!

Исключение - переменные^Wконстанты в интерфейсах, которые всегда public final static. (Это даже в сановско-оракловском тесте по Джаве есть.)

:))

Bioreactor ★★★★★
()
Ответ на: комментарий от Bioreactor

а если сам класс final и поля тоже final (но не static) - всё равно лепить геттеры?

yyk ★★★★★
()
Ответ на: комментарий от Bioreactor

> из-за ограниченности Java

Приведенный код показывает нечитабельность и перегруженность лишними сущностями шарпея, а не «органиченность» Джавы.


Приведённый код не перегружен никакими лишними сущностями. Наоборот, он позволяет определить неявные гетеры и сетеры, что гораздо удобнее явных.

Потому как шарпей - это эклектичная смесь С++ и Выжуал Барсика, где Label1.Caption (нынче Label1.Text) - это тяжелое наследие VB <= 6.0, VBScript и VBA, где объекты не создавались изначально в коде, а только пользовались готовые объекты, напейсанные на COM в C++.


Ничего из того, что тут сказано к обсуждаемой теме отношения не имеет. Графомания вас погубит.

bbk123 ★★★★★
()

Подытожу

Чисто по привычке никогда не оставлял прямого доступа к переменным внутри класса, всегда делал геттер-сеттер. И тут вдруг задумался... А зачем, если можно проще?

Зависит от дизайна. Без целостного восприятия проекта невозможно предугадать, понадобятся или нет геттеры/сеттеры кому и зачем. Например, дизайн библиотек СНАЧАЛА проектируют, а ПОТОМ реализуют в коде (это не относится к AWT — там всё сделано по-быстрому).

iZEN ★★★★★
()
Ответ на: комментарий от lester

Проперти на C++

Если проперти вы здесь понимаете как проперти в C#, то на плюсах можно сделать класс, перегрузить у него оператор = и прочие соответсвующие, а потом в классе создать объект этого класса так, как раньше было названо public свойство. Этим сможет соблюсти backward compatibility и добавить логику на изменение значения свойства.

DiKeert ★★
()
Ответ на: Проперти на C++ от DiKeert

> Если проперти вы здесь понимаете как проперти в C#, то на плюсах можно сделать класс, перегрузить у него оператор = и прочие соответсвующие

я уже писал - оператор "." в С++ перегрузить нельзя

lester ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.