Re[7]: квадратики
От: Me_ Россия  
Дата: 13.09.05 11:52
Оценка:
Здравствуйте, GarryIV, Вы писали:

Me_>>А вот про поведение ничего сказано не было на собеседовании. Если основываться только на формах — то наследование прямоугольник->квадрат — абсолютно правильно.


GIV>Этот случай про квадрат и прямоугольник настолько популярен в литературе посвященной ООП что незнание этого вопроса наталкивает на мысль что ни одной книжки о ООП Вы не читали и что эта тема Вас мало интересует а следовательно уровень Ваших знаний в области ООП недостаточен. Ваши посты только убедили меня в этом мнении.


Вы не поверите, но мне глубоко безразлично ваше мнение о моем профессиональном уровне. Тем более когда его высказывает кто-то, не приводящий в ответ конструктив, а просто высказывающий свое имхо как нечто, не подвергающееся какой-либо критике.
Стыдно должно быть за такой детский сад.
[от модератора]
От: SchweinDeBurg Россия https://zarezky.spb.ru/
Дата: 13.09.05 11:58
Оценка:
Настоятельно предлагается либо прекратить дискуссию, либо вести ее в более конструктивном ключе. В противном случае все нарушители обязательных правил будут награждаться временным ограничением свобод на форумах RSDN.
[ posted via RSDN@Home 1.1.4 stable SR1 r568, accompanied by Iron Maiden — Run To The Hills ]
- Искренне ваш, Поросенок Пафнутий
Re[10]: квадратики
От: LuciferMoscow Россия  
Дата: 13.09.05 13:26
Оценка:
Здравствуйте, Alexey_ch, Вы писали:

A_>Здравствуйте, LuciferMoscow, Вы писали:

LM>>

Наследование надо не для повторного использования, а чтобы быть повторно использованным

A_> Мысль не осилил
Попытаюсь пояснить.
X: public Y нужно не для того, чтобы использовать методы Y в X, а для того, чтобы

Y* pY=new X;
// Далее клиент не знает, что он общается с Х, он думает, что он общается с У.


A_>Значит, например, виртуальная CWnd::WndProc() это чистое зло Сам CWnd не знает, что там происходит.

Приводится пример исключения: Саттер и Александреску называют это "классами стратегий". Насколько я понял, мне данное знакомо под другим названием(Шаблонный метод).

A_>Мне кажется, что Александреску пережевывает надуманную проблему. SetWidth() может быть объявлена как private.

У прямоугольника?

A_>И почему клиенты класса Прямоугольник должны возводить GetWidth() в квадрат? Во-первых они знают, что это прямоугольник, а не квадрат.

Они могут не знать о том, что это прямоугольник!
void f(Y* pY);

Y* pY=new X;
f(pY);

void f(Y* pY)
{
  // на что мы получили уазатель? На Х? На У?
}



LM>>P.S. Цитата переврана, но надеюсь смысл сохранил: "Наследующий класс обязан сохранять инварианты наследуемого"

A_>А каждая база данных должна быть нормализована И еще мир во всем мире...
Денормализация базы вполне допустима для ускорения.
Re[11]: квадратики
От: Alexey_ch Швейцария  
Дата: 13.09.05 15:13
Оценка:
Здравствуйте, LuciferMoscow, Вы писали:

LM>X: public Y нужно не для того, чтобы использовать методы Y в X, а для того, чтобы

LM>
LM>Y* pY=new X;
LM>// Далее клиент не знает, что он общается с Х, он думает, что он общается с У.
LM>

Если бы X: public Y было нужно только для этого, то переопределение невиртуальных функций было бы запрещено. В данном примере мы не можем переопределить поведение методов класса Y, какой тогда смысл в наследовании?

A_>>Мне кажется, что Александреску пережевывает надуманную проблему. SetWidth() может быть объявлена как private.

LM>У прямоугольника?
Именно, т.к. она совсем не нужна дальше в иерархии наследования.
Также можно ее скрыть в классе Квадрат.
class Rectangle
{
public:
    void SetWidth()
    {
    }
};

class Square : public Rectangle
{
private:
    void SetWidth()
    {
    }
};


int main(int argc, char* argv[])
{
    Square s; // никаких Rectangle* r = new Square()
    s.SetWidth(); // ошибка

    return 0;
}


A_>>И почему клиенты класса Прямоугольник должны возводить GetWidth() в квадрат? Во-первых они знают, что это прямоугольник, а не квадрат.

LM>Они могут не знать о том, что это прямоугольник!
Для этого и существуют виртуальные функции. Базовый класс вызывает имплементацию потомка, который в свою очередь знает, кто он такой. Т.е. должна быть вызвана виртуальная функция для вычисления площади.

LM>>>P.S. Цитата переврана, но надеюсь смысл сохранил: "Наследующий класс обязан сохранять инварианты наследуемого"

A_>>А каждая база данных должна быть нормализована И еще мир во всем мире...
LM>Денормализация базы вполне допустима для ускорения.
Это я к тому, что не надо никогда не наследовать квадрат от прямоугольника, потому что какой-то мужик написал в книге, что это плохо.
... << RSDN@Home 1.1.4 beta 7 rev. 0>>
Re[12]: квадратики
От: LuciferMoscow Россия  
Дата: 13.09.05 17:15
Оценка:
Здравствуйте, Alexey_ch, Вы писали:

A_>Здравствуйте, LuciferMoscow, Вы писали:


LM>>X: public Y нужно не для того, чтобы использовать методы Y в X, а для того, чтобы

LM>>
LM>>Y* pY=new X;
LM>>// Далее клиент не знает, что он общается с Х, он думает, что он общается с У.
LM>>

A_>Если бы X: public Y было нужно только для этого, то переопределение невиртуальных функций было бы запрещено. В данном примере мы не можем переопределить поведение методов класса Y, какой тогда смысл в наследовании?
Вообще-то переопределение НЕвиртуальных функций считается дурным тоном. Не запрещено это, возможно, из-за back-совместимости. Запрещеть, что либо в стандарте в принципе не любят. Обычный путь для этого выглядит так:
— в версии Х есть ФИШКА
— в версии У не рекомендуется использовать ФИШКУ
....(обрати внимание на многоточие)
-в версии ZZZZ ФИШКА запрещена.

A_>>>Мне кажется, что Александреску пережевывает надуманную проблему. SetWidth() может быть объявлена как private.

LM>>У прямоугольника?
A_>Именно, т.к. она совсем не нужна дальше в иерархии наследования.
A_>Также можно ее скрыть в классе Квадрат.
A_>
A_>class Rectangle
A_>{
A_>public:
A_>    void SetWidth()
A_>    {
A_>    }
A_>};
Я клиент класса прямоугольник. Как мне измениить ширину? Скрыть? Замечательно. Нарушаем другой инвариант:
[ccode]
CRect* pRect=CreateX(...);
int Size=10;
pRect->SetWigth(Size);
ASSERT( Size == pRect->GetWigth() );


LM>>>>P.S. Цитата переврана, но надеюсь смысл сохранил: "Наследующий класс обязан сохранять инварианты наследуемого"

A_>>>А каждая база данных должна быть нормализована И еще мир во всем мире...
LM>>Денормализация базы вполне допустима для ускорения.
A_>Это я к тому, что не надо никогда не наследовать квадрат от прямоугольника, потому что какой-то мужик написал в книге, что это плохо.
Какой-то мужик? Я бы прислушался к мнению "этого мужика"
Re[9]: квадратики
От: Joker3D Россия http://blog.trunin.com
Дата: 14.09.05 09:42
Оценка:
Здравствуйте, LuciferMoscow, Вы писали:

LM>

LM>Наиболее часто в этой связи два класса — квадрат и прмоугольник.scipped
LM>Квадрат не может быть корректно унаследован от прямоугольника, т.к. SetWidth не изменяем его высоту
LM>Прямоугольник не может быть коррекно унаследован от квадрата, т.к. его клиенты полагают, что для нахождения его площади достаточно возвести в квадрат его ширину


LM>P.S. Цитата переврана, но надеюсь смысл сохранил: "Наследующий класс обязан сохранять инварианты наследуемого"


А почему бы не сделать так:
1. пронаследовать квадрат от прямоугольника
2. переопререлить виртуальные функции SetWidth/Height, чтобы при изменении одной стороны вторая автоматически становилась ей равной.

Кстати, при работе в Visio и других редакторах визуально так всегда и происходит.

PS. А еще лучше оставить невиртуальные SetWidth/Height в каком-нибудь базовом для всех классе Shape и дергать оттуда виртуальные protected virtual OnSetWidth/Height. А в Square их переопределить.
Konstantin Trunin
http://blog.trunin.com — эффективное управление людьми, проектами, собой
Re[6]: квадратики
От: _Obelisk_ Россия http://www.ibm.com
Дата: 14.09.05 12:39
Оценка:
Здравствуйте, Me_, Вы писали:

Me_>А вот про поведение ничего сказано не было на собеседовании. Если основываться только на формах — то наследование прямоугольник->квадрат — абсолютно правильно.


Imho, наследование здесь вообще излишне. Достаточно добавить метод IsSquare() в класс прямоугольника.



Душа обязана трудиться! (с) Н.Заболоцкий.
Re[2]: квадратики
От: Трурль  
Дата: 14.09.05 13:18
Оценка:
Здравствуйте, ilya_ny, Вы писали:

_>собеседование.. 3 мужика

_>1.
_>один нарисовал квадратик, другой взял у него бумажку, подумал немного, и рядом подрисовал прямоугольничек и спращивает : "что от чего порождено ? а нарисуй-ка нам классы!"
_>я говорю, что квадратик порожден от прямоугольничка, на что третий мужичек сразу и говорит : "а не фига вы, молодой человек, ооп не знаете"
_>после этого третий ничего не произнес до самого конца собеседования.

А я бы попросил этого художника изменить длину стороны у нарисованного квадратика, дабы продемонстрировать нарушения LSP. Интересно, как бы у него получилось?
Re[2]: Задания на собеседовании.
От: MaximVK Россия  
Дата: 14.09.05 16:47
Оценка:
Здравствуйте, Mystic, Вы писали:

M>С тобой происходят не самые страшные вещи, история знает примеры и пострашнее.


Спасибо! Давно я так не смеялся
Re[10]: квадратики
От: LuciferMoscow Россия  
Дата: 14.09.05 20:51
Оценка:
Здравствуйте, Joker3D, Вы писали:

JD>Здравствуйте, LuciferMoscow, Вы писали:


JD>А почему бы не сделать так:

JD>1. пронаследовать квадрат от прямоугольника
JD>2. переопререлить виртуальные функции SetWidth/Height, чтобы при изменении одной стороны вторая автоматически становилась ей равной.
В базовом классе? Методы SetWight,SetHeight для круга и треугольника ты тоже переопределять будешь?

JD>Кстати, при работе в Visio и других редакторах визуально так всегда и происходит.

JD>PS. А еще лучше оставить невиртуальные SetWidth/Height в каком-нибудь базовом для всех классе Shape и дергать оттуда виртуальные protected virtual OnSetWidth/Height. А в Square их переопределить.
См. выше.
Re[11]: квадратики
От: Joker3D Россия http://blog.trunin.com
Дата: 15.09.05 08:03
Оценка:
Здравствуйте, LuciferMoscow, Вы писали:

LM>Здравствуйте, Joker3D, Вы писали:


JD>>Здравствуйте, LuciferMoscow, Вы писали:


JD>>А почему бы не сделать так:

JD>>1. пронаследовать квадрат от прямоугольника
JD>>2. переопререлить виртуальные функции SetWidth/Height, чтобы при изменении одной стороны вторая автоматически становилась ей равной.
LM>В базовом классе? Методы SetWight,SetHeight для круга и треугольника ты тоже переопределять будешь?
Посмотри Visio.
Там и у треугольника и у круга есть Width и Height. А специфические свойства — типа радиуса уже есть только у круга. Эти специфические свойства вычислимые от Width/Height!
Я когда-то разрабатывал свой аналог визио и именно так все и реализовал — и получилось очень удобно.

Выдели в Visio какую-нибудь фигуру и посмотри: Window->Show ShapeSheet.

JD>>Кстати, при работе в Visio и других редакторах визуально так всегда и происходит.

JD>>PS. А еще лучше оставить невиртуальные SetWidth/Height в каком-нибудь базовом для всех классе Shape и дергать оттуда виртуальные protected virtual OnSetWidth/Height. А в Square их переопределить.
LM>См. выше.
См. выше.
Konstantin Trunin
http://blog.trunin.com — эффективное управление людьми, проектами, собой
Re[9]: квадратики
От: Joker3D Россия http://blog.trunin.com
Дата: 15.09.05 08:34
Оценка:
Здравствуйте, Ulin, Вы писали:

U>

U>At this point in time we have two classes, Square and Rectangle, that appear to work.
U>No matter what you do to a Square object, it will remain consistent with a mathematical
U>square. And regardless of what you do to a Rectangle object, it will remain a mathe-
U>matical rectangle. Moreover, you can pass a Square into a function that accepts a pointer
U>or reference to a Rectangle, and the Square will still act like a square and will remain
U>consistent.
U>Thus, we might conclude that the model is now self consistent, and correct. However,
U>this conclusion would be amiss. A model that is self consistent is not necessarily consis-
U>tent with all its users! Consider function g below.
U>void g(Rectangle& r)
U>{
U>r.SetWidth(5);
U>r.SetHeight(4);
U>assert(r.GetWidth() * r.GetHeight()) == 20);
U>}
U>This function invokes the SetWidth and SetHeight members of what it believes
U>to be a Rectangle. The function works just fine for a Rectangle, but declares an
U>assertion error if passed a Square. So here is the real problem: Was the programmer who
U>wrote that function justified in assuming that changing the width of a Rectangle leaves
U>its height unchanged?
U>Clearly, the programmer of g made this very reasonable assumption. Passing a
U>Square to functions whose programmers made this assumption will result in problems.
U>Therefore, there exist functions that take pointers or references to Rectangle objects,


Пример хороший!
Он вроде как доказывает что нельзя Square наследовать от Rectanle.
А давайте еще подумаем. Если я создам какой-нибудь SmartRectangle производный от Rectangle и его смартовость будет заключаться в том что:
— он, например, умеет липнуть к сетке, корректируя при этом свои размеры (такое бывает и это можно реализовать именно внутри SmartRectangle),
— или, например, его размер зависит от заключенного в нем текста (часто очень полезная фишка)
В обоих этих случаях у меня в функции g() возникнет ассерт!
Значит ли это что я и никакой SmartRectangle не могу наследовать от Rectangle? Так можно прийти к тому что ВСЕ объекты ни будут ни от кого наследоваться....

Я, думаю, что просто следует определиться заранее со свойствами и со стратегией поведения. И уже от этого и плясать.
И если вам важно чтобы выполнялся тест-кейс g(), то тогда да! Нельзя наследовать.
А если у вас есть другие требования, и на тест-кейс g() вам наплевать, то наследуйте как хотите и от чего хотите.

См. http://www.rsdn.ru/Forum/Message.aspx?mid=1381652&amp;only=1
Автор: Joker3D
Дата: 14.09.05


IMHO, главное в проекте — это его успешность. А если тебе для успешности, ускорения разработки, удобства пользования или чего-то еще удобно пронаследовать попугая от крокодила — флаг тебе в руки.
(Только не забудь это задокументировать чтобы потом биологи не ломали голову почему их тест-кейсы валятся )
Konstantin Trunin
http://blog.trunin.com — эффективное управление людьми, проектами, собой
Re[5]: квадратики и ООП
От: gribunin Россия  
Дата: 16.09.05 13:26
Оценка: 2 (2) +1 -1
F>то что прямоугольник порожден от квадрата следует из того, что квадрат можно описать одним свойством
F>длина его стороны(a), а у прямоугольника появляется новое свойство — длина другой стороны (в). Итого прямоугольник наследуется от квадрата с появлением дополнительного своего свойства.

В общем случае, порождённый класс является частным случаем базового. Например, Круг -- частный случай двумерной фигуры, сотрудник отдела закупок -- частный случай просто сотрудника и т.п. Квадрат явно является частным случаем прямоугольника (когда ширина и высота прямоугольника равны), следовательно логично его наследовать именно от прямоугольника.

Плюсы такого наследования по сравнению с наследованием наоборот (прямоугольник от квадрата) очевидны. Например, реализация методов рисования фигуры, вычисления площади и т.п. В случае, когда квадрат наследуется от прямоугольника, их можно реализовать только в базовом классе (прямоугольнике) и они отлично будут работать и для производного класса (квадрата). В обратном случае, придётся писать две малосвязанные реализации в обоих классах.
----------------
Кирилл Грибунин
Re[7]: квадратики
От: gribunin Россия  
Дата: 16.09.05 13:34
Оценка:
Здравствуйте, _Obelisk_, Вы писали:

_O_>Imho, наследование здесь вообще излишне. Достаточно добавить метод IsSquare() в класс прямоугольника.


Может излишне, а может и нет -- это зависит от задачи. Если мы хотим иметь объект, у которого ширина ВСЕГДА равна высоте, то мы должны либо породить соответствующий класс, либо, если пойти по пути с IsSquare(), вносить в существующий класс методы типа SetSquare().
----------------
Кирилл Грибунин
Re[6]: квадратики
От: lpvoid Россия  
Дата: 04.07.06 10:39
Оценка:
Здравствуйте, LuciferMoscow, Вы писали:

<skipped>
LM>>Если так, то отрыв рук — самое мягкое что следует делать за такое. += и + разные вещи, а человек,который будет сопровождать ЭТО должен догадыватся, что какой-то "умник" ТАК переопределил +
LM>execve, с чем Вы не согласны?
Ну вообще-то operator+ делать членом класса не есть гут, ибо при a = a + 1 будет гут, а при a = 1 + a будет совсем не гут
Re: Задания на собеседовании.
От: ArtemGorikov Австралия жж
Дата: 04.07.06 10:58
Оценка:
Рассматривай собеседование как развлечение, азартную игру. Когда попадается сильный интервьюер — это наоборот интересно, можно узнать для себя что-нибудь новое. Если стало скучно или по каким-либо причинам решил для себя, что не хочешь работать с этим человеком — можно просто извиниться и уйти.
Re[7]: квадратики
От: anton_t Россия  
Дата: 04.07.06 11:35
Оценка: +2
Здравствуйте, Me_, Вы писали:

Me_>Здравствуйте, vpedak, Вы писали:


V>>слышал конечно, но new != override. А разговор был именно про него —

V>>"типа на обычную фун-цию слово override поставить нельзя" (ваши слова).
V>>Так вот на обычную функцию слово override поставить таки нельзя. Хотя
V>>new конечно можно.

Me_>Ясно, мы не поняли друг друга.

Me_>"типа на обычную фун-цию слово override поставить нельзя" — это я как процитировал своего интервьера, т.к. про new ему скорее всего ничего известно не было.

Когда ставишь new, то функция не переопределяется, а перекрывается. И получается совсем другое поведение.
Re: Задания на собеседовании.
От: NikeByNike Россия  
Дата: 04.07.06 14:12
Оценка:
Здравствуйте, Sh1ZoID, Вы писали:

SZI> В скором времени собираюсь менять место работы, а значит, таскаться по собеседованиям. Собеседований, как таковых, я не боюсь, т.к. уверен в своих знаниях, но вот когда мне говорят фразу типа: "вот вам небольшое задание, вы должны его сделать за пол часа", кисти моих рук начинают колебаться с амплитудой 5-10см, не зависимо от сложности задания. И когда я сожусь за комп, я не то, что сообразить ничего не могу, я по клавишам-то с трудом попадаю(серьёзно!) . Это для меня самое страшное на собеседовании!!! Так вот собственно вопрос...не будет ли не корректным с моей стороны попросить пройти этот этап собеседования каким-нибудь другим путём? Если это допустимо, то что можно предложить в замен?


SZI> ЗЫ Два раза я напарывался на это, причём оба раза провалился с крахом!!! А после одного из них, я настолько, извините за выражение, "обделался", что даже не смог вспомнить, что вызов метода через IDispatch::Invoke называется поздним связыванием!!!



Еще бывает сложная задача — угадать (именно угадать) какое решение от тебя хотят. Многие задачи имеют несколько решений:
например вопрос — какой недостаток у STL ты знаешь? Или лучше так: Какой ГЛАВНЫЙ недостаток у STL?
Варианты ответов сходу:
непереносимость между dll, отсутствие стратегий, распухание кода. Для меня эти недостатки идут именно в таком порядке. Для работодателя могут идти в другом — и впечатление смазывается.

Или допустим задача — вывести односвязный список в обратном порядке.
Собеседующему могут нравиться красивость кода — решение рекурсией. Или надежность — два цикла.

Научишься угадывать чего от тебя ждут — не пропадешь
Нужно разобрать угил.
Re[6]: квадратики и ООП
От: mihoshi Россия  
Дата: 04.07.06 14:21
Оценка: +1
Здравствуйте, gribunin, Вы писали:

G>В общем случае, порождённый класс является частным случаем базового. Например, Круг -- частный случай двумерной фигуры, сотрудник отдела закупок -- частный случай просто сотрудника и т.п. Квадрат явно является частным случаем прямоугольника (когда ширина и высота прямоугольника равны), следовательно логично его наследовать именно от прямоугольника.


Это уже пережевывалось. Квадрат можно наследовать от прямоугольника, если класс прямоугольника не позволяет независимо менять размеры сторон, кроме как в конструкторе. В противном случае наследование нарушит принцип Лисков.
Re[7]: квадратики и ООП
От: Pyromancer  
Дата: 04.07.06 18:56
Оценка:
Здравствуйте, mihoshi, Вы писали:

M>Здравствуйте, gribunin, Вы писали:


G>>В общем случае, порождённый класс является частным случаем базового. Например, Круг -- частный случай двумерной фигуры, сотрудник отдела закупок -- частный случай просто сотрудника и т.п. Квадрат явно является частным случаем прямоугольника (когда ширина и высота прямоугольника равны), следовательно логично его наследовать именно от прямоугольника.


M>Это уже пережевывалось. Квадрат можно наследовать от прямоугольника, если класс прямоугольника не позволяет независимо менять размеры сторон, кроме как в конструкторе. В противном случае наследование нарушит принцип Лисков.


Геометрия говорит, что прямоугольник и ромб наследуют от паралеллограмма, а квадрат от прямоугольника и ромба, а значит подстраивайте своё ООП соответственно.
Даже если прямоугольник имеет раздельное изменение сторон кто мешает в квадрате оставить ширину и высоту а метод переопределить так, чтобы и второе измерение изменялась так же как то,что меняют? Или например наследовать этот метод от ромба без изменений
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.