Сорри, за возможный оффтоп, но вряд ли кто-либо кроме участников этого форума знает ответ.
Вопрос такой... Никто не в курсе, кто автор задачки "про квадрат и прямоугольник" (что-то типа):
Дано две сущности: квадрат и прямоугольник. Они обладают следующим поведением:
1. Предоставляют информацию о своих размерах.
2. Могут изменять свои размеры.
3. Предоставляют информацию о своей площади.
Вопрос: Кто из них родитель, а кто предок? Почему?
Я всегда считал, что в свое время "подсмотрел" её у Буча... Но вот что-то сегодня полистал его — ничего похожего не нашёл. Но, блин, вряд ли я её сам придумал
Здравствуйте, gbear, Вы писали:
G>День добрый...
G>Сорри, за возможный оффтоп, но вряд ли кто-либо кроме участников этого форума знает ответ.
G>Вопрос такой... Никто не в курсе, кто автор задачки "про квадрат и прямоугольник" (что-то типа):
G>Дано две сущности: квадрат и прямоугольник. Они обладают следующим поведением:
G>1. Предоставляют информацию о своих размерах. G>2. Могут изменять свои размеры. G>3. Предоставляют информацию о своей площади.
G>Вопрос: Кто из них родитель, а кто предок? Почему?
G>Я всегда считал, что в свое время "подсмотрел" её у Буча... Но вот что-то сегодня полистал его — ничего похожего не нашёл. Но, блин, вряд ли я её сам придумал
G>--- G>С уважением, Сиваков Константин
Я не в курсе, увы. И задачу вижу в первый раз.
Считаю, что правильный ответ: родитель — квадрат.
Можно узнать правильный ответ?
Здравствуйте, gbear, Вы писали:
G>День добрый...
G>Сорри, за возможный оффтоп, но вряд ли кто-либо кроме участников этого форума знает ответ.
G>Вопрос такой... Никто не в курсе, кто автор задачки "про квадрат и прямоугольник" (что-то типа):
G>Дано две сущности: квадрат и прямоугольник. Они обладают следующим поведением:
G>1. Предоставляют информацию о своих размерах. G>2. Могут изменять свои размеры. G>3. Предоставляют информацию о своей площади.
G>Вопрос: Кто из них родитель, а кто предок? Почему?
G>Я всегда считал, что в свое время "подсмотрел" её у Буча... Но вот что-то сегодня полистал его — ничего похожего не нашёл. Но, блин, вряд ли я её сам придумал
Здравствуйте, LtrK2, Вы писали:
LK>Здравствуйте, gbear, Вы писали:
...
LK>Я не в курсе, увы. И задачу вижу в первый раз. LK>Считаю, что правильный ответ: родитель — квадрат. LK>Можно узнать правильный ответ?
Почему квадрат?
Вообще ни квадрат ни прямоугольник с т. зр. ООП, т.к. полиморфизм нарушается, единственное мы можем вынести общий интерфейс, но в каждом классе будут частные вещи, которых нет в другом (или поедение оных будет отличным == нарушение полиморфизма, принципа Лисков).
Здравствуйте, gbear, Вы писали:
G>Вопрос: Кто из них родитель, а кто предок? Почему?[/i]
В данном случае названия неудачные, т.к. в определение квадрата не входит инвариант
ширина=высота. Поэтому не все квадраты в описанном случае будут являтся квадратами с точки зрения геометрии.
С другой стороны, можно сами названия Квадрат и Прямоугольник рассматривать как отсылку к математике и неявной декларацией подобных инвариантов.
А еще бывают языки типа cecil где класс можно декларативно определить (типа квадрат это прямоугольник у которого длина=ширина) и конкретный объект классифицируется динамически на основе такого определения.
Здравствуйте, LtrK2, Вы писали:
LK>Я не в курсе, увы. И задачу вижу в первый раз.
Жаль
LK>Считаю, что правильный ответ: родитель — квадрат.
Главный-то вопрос объяснить почему
LK>Можно узнать правильный ответ?
Вообще говоря — его как бы и нет Есть теоритически правильный ответ, базирующийся на том утверждении, что сущности обладающие подобным поведением (не в смысле таким... а в смысле, что поведения этих сущностей подобны) лежат на одном уровне иерархии классов.
В реальности это не всегда так.
Здравствуйте, cranky, Вы писали:
LK>>Считаю, что правильный ответ: родитель — квадрат.
C>скорее прямоугольник, у него ширина и высота, а квадрат — это уже его специализация, где w==h
А если рассмотреть целые и действительный числа — что из них родитель, а что предок?
Неа... Он подходит к этому вопросу (да и вопрос-то, вообще говоря не совсем тот ) с точки зрения конкретной реализации поведения. А данный вопрос, вообще говоря, "разрешим" на уровне "чистых сущностей" — и не имеет к контретным реализациям их поведения никакого отношения. Тем более — или мне показалось? — он совсем не рассмотрел в этой работе вариант S<-R что ооочень странно.
Кароче, не то это... Хотя, действительно, похоже...
G>Здравствуйте, dshe, Вы писали:
D>>Может D>>The Liskov Substitution Principle D>>Robert C. Martin D>>C++ Report, 1996 D>>http://www.objectmentor.com/resources/articles/lsp.pdf
G>Неа... Он подходит к этому вопросу (да и вопрос-то, вообще говоря не совсем тот ) с точки зрения конкретной реализации поведения. А данный вопрос, вообще говоря, "разрешим" на уровне "чистых сущностей" — и не имеет к контретным реализациям их поведения никакого отношения. Тем более — или мне показалось? — он совсем не рассмотрел в этой работе вариант S<-R что ооочень странно.
G>Кароче, не то это... Хотя, действительно, похоже...
Это именно то. То есть правильный ответ, пожалуй, не Мартин, а Лискова.
А на уровне "чистых сущностей" иерархии не будет вообще.
Здравствуйте, gbear, Вы писали:
G>Здравствуйте, Курилка, Вы писали:
К>>Вообще ни квадрат ни прямоугольник с т. зр. ООП, т.к. полиморфизм нарушается
G>Ээээ... По поводу нарущения полиморфизма можно по подробнее. Такое возражение слушу в первые.
Да всё просто у тебя есть ширина и длина, так?
Берём за предка квадрат, тогда ширина==длина и изменение одной влечёт за собой изменение другой, наследуем от него прямоугольник, НО ширина!=длина, т.е. поведение объекта совпадает с поведением предка, ну нельзя сказать что любой прямоугольник есть квадрат => нарушение LSP.
Если берём обратный вариант (и более естественный с т.зр. геометрии), то получаем неожиданное поведение у квадрата (если рассматривать его абстрактно как прямоугольник): изменение ширины вдруг магическим образом должно вызывать изменение длины и наоборот, т.е. поведение квадрата будет отличаться от поведения прямоугольника (точнее будут отличаться следствия функций-аксессоров для длины/ширины). Нарушение меньшее чем в 1-м случае, но всё равно чреватое...
(E.g. мы сохранили длину прямоугольника, который квадрат на самом деле, потом поменяли ширину и в сохранённом значении длины у нас уже "левое" значение)
Здравствуйте, mihoshi, Вы писали:
M>Здравствуйте, cranky, Вы писали:
LK>>>Считаю, что правильный ответ: родитель — квадрат.
C>>скорее прямоугольник, у него ширина и высота, а квадрат — это уже его специализация, где w==h
M>А если рассмотреть целые и действительный числа — что из них родитель, а что предок?
Здравствуйте, Andrei N.Sobchuck, Вы писали:
ANS>Это именно то. То есть правильный ответ, пожалуй, не Мартин, а Лискова.
По-моему, фамилия Лисков не склоняется. По крайней мере везде в русскоязычной литературе было написано "принцип Лисков (Барбара Лисков)", а не "принцип Лисковой"
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, mihoshi, Вы писали:
M>Здравствуйте, cranky, Вы писали:
LK>>>Считаю, что правильный ответ: родитель — квадрат.
C>>скорее прямоугольник, у него ширина и высота, а квадрат — это уже его специализация, где w==h
M>А если рассмотреть целые и действительный числа — что из них родитель, а что предок?
Думается, что у них просто общий абстрактный предок (или интерфейс), определяющий общие операции.
Здравствуйте, Курилка, Вы писали:
К>Здравствуйте, gbear, Вы писали:
К>Да всё просто у тебя есть ширина и длина, так?
Вообще-то нет Есть длины сторон. Квадрат задается одной такой длиной. Прямоугольник двумя... Но, походу, не суть.
К>Берём за предка квадрат, тогда ширина==длина и изменение одной влечёт за собой изменение другой, наследуем от него прямоугольник, НО ширина!=длина, т.е. поведение объекта совпадает с поведением предка, ну нельзя сказать что любой прямоугольник есть квадрат => нарушение LSP.
Да не факт, собственно. Ну будет агрегат работать с прямоугольником как с квадратом... Тут уже все уперается в особенности реализации "ф-ции" изменения размеров. Её ведь и так можно написать, что если с прямоугольником работать как с квадратом — задавая его длиной одной стороны — то он "превратиться" в "квадрат". Так что, повторюсь, для меня например весьма странно было, что в том документе, где приведена похожая задача не рассмотрен вариант S<-R.
К>Если берём обратный вариант (и более естественный с т.зр. геометрии), то получаем неожиданное поведение у квадрата (если рассматривать его абстрактно как прямоугольник): изменение ширины вдруг магическим образом должно вызывать изменение длины и наоборот, т.е. поведение квадрата будет отличаться от поведения прямоугольника (точнее будут отличаться следствия функций-аксессоров для длины/ширины). Нарушение меньшее чем в 1-м случае, но всё равно чреватое...
ИМХО, тут-то как раз нарушения безусловно есть — в варианте S<-R их можно избежать.
Здравствуйте, Andrei N.Sobchuck, Вы писали:
G>>Кароче, не то это... Хотя, действительно, похоже...
ANS>Это именно то. То есть правильный ответ, пожалуй, не Мартин, а Лискова.
Да не то... Именно потому, что автор уже оперирует сигнатурами методов и т.п. Т.е. работает с конкретной реализацией. Та же "задача", которую я имею ввиду — ставилась на этапе анализа предметной области. Т.е. мы только выявили что у нас будет две сущности... и т.д. Мы ещё не задумываемся над тем как именно будет реализовываться поведение... нет у нас сигнатур.
ANS>А на уровне "чистых сущностей" иерархии не будет вообще.
Угу... Зато на уровне "чистых сущностей" уже можно оценить какие отношения будут между классами, реализующие данные сущности. Собственно, практическая ценность, если можно так выразиться, данного вопроса — суть, выявление "интерфейсных" сущностей уже на этапе анализе предметной области — как известно, на этом этапе, просто так их не выявить.
Здравствуйте, gbear, Вы писали:
G>Здравствуйте, Курилка, Вы писали:
К>>Здравствуйте, gbear, Вы писали:
К>>Да всё просто у тебя есть ширина и длина, так?
G>Вообще-то нет Есть длины сторон. Квадрат задается одной такой длиной. Прямоугольник двумя... Но, походу, не суть.
К>>Берём за предка квадрат, тогда ширина==длина и изменение одной влечёт за собой изменение другой, наследуем от него прямоугольник, НО ширина!=длина, т.е. поведение объекта совпадает с поведением предка, ну нельзя сказать что любой прямоугольник есть квадрат => нарушение LSP.
G>Да не факт, собственно. Ну будет агрегат работать с прямоугольником как с квадратом... Тут уже все уперается в особенности реализации "ф-ции" изменения размеров. Её ведь и так можно написать, что если с прямоугольником работать как с квадратом — задавая его длиной одной стороны — то он "превратиться" в "квадрат". Так что, повторюсь, для меня например весьма странно было, что в том документе, где приведена похожая задача не рассмотрен вариант S<-R.
Вот код:
class S
{
int side_;
virtual int Width
{
get
{
return side_;
}
}
virtual int Height
{
get
{
return Width;
}
}
}
class R:S
{
int height_;
int width_;
override int Width
{
get
{
return width__;
}
}
override int Height
{
get
{
return height_;
}
}
}
Это то, что ты имеешь в виду? Если да, то это просто явная бага в логике — ну не нужно нам для КВАДРАТА иметь длину и ширину, т.к. нам нужна только сторона и площадь мы будем получать квадратом её, а никак не произведением сторон. Т.е. получаем, что твой "квадрат" описывает больше того, что он должен описывать, т.е. для пользователя становится нужным знание, что от квадрата может унаследоваться прямоугольник, поэтому нужны 2 стороны. Имхо с т.зр. логики это просто бред. Может ты ещё и число сторон включишь и массив их длин и углов, дабы вообще произвольный многоугольник описывать?
Здравствуйте, gbear, Вы писали:
G>Здравствуйте, Курилка, Вы писали:
К>>Если берём обратный вариант (и более естественный с т.зр. геометрии), то получаем неожиданное поведение у квадрата (если рассматривать его абстрактно как прямоугольник): изменение ширины вдруг магическим образом должно вызывать изменение длины и наоборот, т.е. поведение квадрата будет отличаться от поведения прямоугольника (точнее будут отличаться следствия функций-аксессоров для длины/ширины). Нарушение меньшее чем в 1-м случае, но всё равно чреватое...
G>ИМХО, тут-то как раз нарушения безусловно есть — в варианте S<-R их можно избежать.
class S
{
private int _size;
public virtual int Size
{
get
{
return _size;
}
set
{
_size = value;
}
}
}
class R : S
{
private int _size;
public int Height
{
get
{
return base.Size;
}
set
{
base.Size = value;
}
}
public int Width
{
get
{
return this._size;
}
set
{
this._size = value;
}
}
public override int Size
{
get
{
return base.Size;
}
set
{
base.Size = value;
this._size = value;
}
}
}
Реализация R.get_Size может быть различной.... такой какой нам нужно будет — вплоть до вызова R.set_Size(base.Size) перед ретурном. Не суть...