И все-таки квадрат это прямоугольник
От: igna Россия  
Дата: 03.03.07 07:48
Оценка: +6
Все-таки математика права, квадрат это прямоугольник, и в приведенном ниже коде (на Java) нет ничего неприличного:

class Rectangle {
    int width, height;

    public Rectangle(int width, int height) {
        this.width = width;
        this.height = height;
    }
    public int Width() {
        return width;
    }
    public int Height() {
        return height;
    }
}

class Square extends Rectangle {
    public Square(int side) {
        super(side, side);
    }
}


А если захотелось добавить методы SetWidth и SetHeight, так это уже нечто за пределами математических понятий "квадрат" и "прямоугольник". В математике объекты (не в смысле ООП объекты, нет, в обычном, человеческом смысле объекты), так вот, в математике объекты как правило неизменные, то есть умножая одну матрицу на другую получаем третью, а вовсе не модифицируем первую. В программировании такие объекты тоже встречаются, например String в Java или .NET; и если Rectangle и Square определить неизменными, они вполне могут быть связаны отношением наследования.
Re: И все-таки квадрат это прямоугольник
От: FDSC Россия consp11.github.io блог
Дата: 03.03.07 09:12
Оценка:
Здравствуйте, igna, Вы писали:

I>Все-таки математика права, квадрат это прямоугольник, и в приведенном ниже коде (на Java) нет ничего неприличного:


I>А если захотелось добавить методы SetWidth и SetHeight, так это уже нечто за пределами математических понятий "квадрат" и "прямоугольник". В математике объекты (не в смысле ООП объекты, нет, в обычном, человеческом смысле объекты), так вот, в математике объекты как правило неизменные, то есть умножая одну матрицу на другую получаем третью, а вовсе не модифицируем первую. В программировании такие объекты тоже встречаются, например String в Java или .NET; и если Rectangle и Square определить неизменными, они вполне могут быть связаны отношением наследования.


И зачем такое нужно??? Это уже ближе к ФП...

Вот представь. Скажем, есть у меня задача разбить плоскость на несколько прямоугольников. Я как-нибудь итеративно это буду делать (ну, я "от балды" пример привёл), каждую итерацию изменяя размеры прямоугольника. И что, я буду ради этих мат. сущностей себе удобство программирования портить????

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

Потому что программный код — это модель ПРОГРАММЫ, а не реальных вещей, и там мы можем делать всё, что хотим на свой страх и риск... ну, а потом за это отвечать, может быть, придётся
Re[2]: И все-таки квадрат это прямоугольник
От: igna Россия  
Дата: 03.03.07 09:57
Оценка: +2
Здравствуйте, FDSC, Вы писали:

FDS>И зачем такое нужно???


Да может быть практически и не нужно, только чтоб ясность была.

Нередко попадается мнение, что то "в программировании квадрат — не прямоугольник", то вообще "прямоугольник нужно наследовать от квадрата". И хотя объяснение кажущемуся парадоксу имеется, вот оно например: http://www.objectmentor.com/resources/articles/lsp.pdf, но очень уж там много, намного больше чем нужно.

На самом деле обьяснение может быть совсем простым: квадрат это прямоугольник (как и в математике), но изменяемый квадрат не является изменяемым прямоугольником. В программировании обычно объекты изменяемые, ну мы и привыкли называть изменяемые квадрат и прямоугольник просто квадратом и просто прямоугольником, а потом вдруг вспоминаем про школьные квадрат и прямоугольник, и все, вот они три сосны и блуждающие среди них программисты.
Re: И все-таки квадрат это прямоугольник
От: VoidEx  
Дата: 03.03.07 10:33
Оценка: 1 (1) +1 -4
Здравствуйте, igna, Вы писали:

I>Все-таки математика права, квадрат это прямоугольник, и в приведенном ниже коде (на Java) нет ничего неприличного:


Все здесь неприлично. Наследование — это расширение понятия, когда все экзмепляры A являются также экзмеплярами B, но ни один экзмепляр B не является экземпляром A.
Тут же квадрат — это частный случай прямоугольника, да он им является, но из всего множества возможных прямоугольников некоторые являются квадратами.
Re: И все-таки квадрат это прямоугольник
От: jedi Мухосранск  
Дата: 03.03.07 11:06
Оценка: 1 (1) +3 -1
Здравствуйте, igna, Вы писали:

I>Все-таки математика права, квадрат это прямоугольник, и в приведенном ниже коде (на Java) нет ничего неприличного:


Мне эти разговоры о наследовании квадрата от прямоугольника (или наоборот) всегда казались глупыми. На самом деле это два разных типа, но:
1) преобразование типа КВАДРАТ->ПРЯМОУГОЛЬНИК имеет смысл всегда;
2) преобразование типа ПРЯМОУГОЛЬНИК->КВАДРАТ имеет смысл только когда ширина равна высоте.

В информатике есть куча подобных примеров. Например типы short & long. Для них также верны утверждения (1) & (2), но почему-то никому в здравом уме не приходит в голову наследовать short от long (или наоборот)
... << RSDN@Home 1.2.0 alpha rev. 0>>
Ахринеть :)
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.03.07 11:23
Оценка: +2 :))) :)))
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: И все-таки квадрат это прямоугольник
От: FDSC Россия consp11.github.io блог
Дата: 03.03.07 11:27
Оценка:
Здравствуйте, igna, Вы писали:

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


FDS>>И зачем такое нужно???


I>Да может быть практически и не нужно, только чтоб ясность была.


Ну вот я и говорю: такие вещи только запутывают. Ясность — она в каждом конкретном приложении своя
Впрочем, никто не мешает пообсуждать это в десятый раз...
Re: И эти люди...
От: McSeem2 США http://www.antigrain.com
Дата: 03.03.07 18:46
Оценка: 6 (3) +3
...утверждают, что парадигма наследования имеет хоть какую-то практическую пользу?! Гы-сына-лол.

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

I>Все-таки математика права, квадрат это прямоугольник


Раз уж на то пошло, отношение наследования, которое связывает квадрат и прямоугольник притянуто за уши и не имеет ни малейшего практического смысла. Правильно надо делать так: Квадрат — это Фигура, Прямоугольник — это Фигура, Треугольник — это Фигура. Ну и т.д. А то, что в геометрии квадрат является прямоугольником, то этот "гондурас" вообще не должен беспокоить, ибо этот факт является ортогональным по отношению к понятию наследования. Но для реализации такого соотношения как "Квадрат — это Фигура, Прямоугольник — это Фигура" наследование вообще не нужно. Это вообще не является наследованием. По сути это — имплементация интерфейса, или даже можно сказать, реализация контракта.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[2]: И эти люди...
От: _nn_ www.nemerleweb.com
Дата: 03.03.07 21:19
Оценка: -1
Здравствуйте, McSeem2, Вы писали:

MS>...утверждают, что парадигма наследования имеет хоть какую-то практическую пользу?! Гы-сына-лол.


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


I>>Все-таки математика права, квадрат это прямоугольник


MS>Раз уж на то пошло, отношение наследования, которое связывает квадрат и прямоугольник притянуто за уши и не имеет ни малейшего практического смысла. Правильно надо делать так: Квадрат — это Фигура, Прямоугольник — это Фигура, Треугольник — это Фигура. Ну и т.д. А то, что в геометрии квадрат является прямоугольником, то этот "гондурас" вообще не должен беспокоить, ибо этот факт является ортогональным по отношению к понятию наследования. Но для реализации такого соотношения как "Квадрат — это Фигура, Прямоугольник — это Фигура" наследование вообще не нужно. Это вообще не является наследованием. По сути это — имплементация интерфейса, или даже можно сказать, реализация контракта.


+1.

Вот надумалось:

Вариант 1:
interface IFigure
{}

interface IWidth
{
 public int Width
 { get };
}

interface IHeight
{
 public int Height
 { get };
}

interface IRectangle : IWidth, IHeight
{
}

class Rectangle : IRectangle
{
 public int Width
 { get { return _width; } };
 public int Height
 { get { return _height; } };
 
 private int _width;
 private int _height;
}

interface ISide
{
 public int Side
 { get };

 public int Angle
 { get };
}

interface IRhombus : ISide
{}

class Rhombus : IRhombus
{
 public int Side
 { get { return _side; } };

 public int Angle
 { get { return _angle; } };

 int _side;
 int _angle;
}

interface ISquare : IRectangle , IRhombus

class Square : ISquare
{
 public int Width
 { get { return _width; } };
 public int Height
 { get { return _height; } };
 
 private int _width;
 private int _height;

 public int Side
 { get { return _side; } };

 public int Angle
 { get { return _angle; } };

 int _side;
 int _angle;

 // код для сохранения _width == _height == _side && _angle == 90  :maniac: 
}


Что тут получили.
Квадрат он поддерживает интерфейс прямоугольника и ромба.
Однако появляется лишний код, который не связан с квадратом.

Решение через контракт мне нравится больше:
Вариант 2:
[Contract(ISquare, Width == Height)]
interface IRectangle
{...}

class Rectangle : IRectangle
{...}

[Contract(ISquare, Angle == 90)]
interface IRhombus
{...}

class Rhombus : IRhombus
{...}


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

С другой стороны нужно как-то красиво организовать поддержку контрактом иначе можно сходу не понять в чем проблема:
void f(ISquare) {...}

Rectangle r1 = new Rectange(1,1); // r1 : ISquare
Rectangle r2 = new Rectange(1,2); // r2 : IRectangle

f(r1); // OK
f(r2); // Ошибка ??
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: И эти люди...
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 03.03.07 21:55
Оценка: 1 (1) +2 -1
Здравствуйте, _nn_, Вы писали:

Господи, зачем так все запутывать?
interface IRectangle
{
    int Width {get;}
    int Height {get;}
}

interface ISquare : IRectangle
{
    int Size {get;}
}

class Rectangle : IRectangle
{
    int _width;
    int _height;
    ...
}

class Square : ISquare
{
    int _size;
    ...
}

Предельно простой код, никаких нарушений LSP и никаких парадоксов.
... << RSDN@Home 1.2.0 alpha rev. 675 on Windows Vista 6.0.6000.0>>
AVK Blog
Re: И все-таки квадрат это прямоугольник
От: Владек Россия Github
Дата: 03.03.07 22:01
Оценка:
Здравствуйте, igna, Вы писали:

I>А если захотелось добавить методы SetWidth и SetHeight, так это уже нечто за пределами математических понятий "квадрат" и "прямоугольник".


В математическом смысле вы правы — можно ввести такую бинарную операцию над элементами множества, что результат её выполнения не будет принадлежать исходному множеству. Это свойство имеет название, но я его забыл. Пример: операция деления натуральных чисел, результат не всегда является натуральным числом (1/2=0.5).

I>В математике объекты (не в смысле ООП объекты, нет, в обычном, человеческом смысле объекты), так вот, в математике объекты как правило неизменные, то есть умножая одну матрицу на другую получаем третью, а вовсе не модифицируем первую.


Это мысленные абстракции — очень дешёвый материал, можно транжирить.

I>В программировании такие объекты тоже встречаются, например String в Java или .NET; и если Rectangle и Square определить неизменными, они вполне могут быть связаны отношением наследования.


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

Что нового?
Джентльмены не матерятся, они просто говорят: "Your bunny wrote!"
Re[2]: И все-таки квадрат это прямоугольник
От: igna Россия  
Дата: 03.03.07 23:06
Оценка: 1 (1) +1
Здравствуйте, VoidEx, Вы писали:

VE>Все здесь неприлично. Наследование — это расширение понятия, когда все экзмепляры A являются также экзмеплярами B, но ни один экзмепляр B не является экземпляром A.


Предположим, что A наследует B, а x является экземпляром A. Поскольку "все экзмепляры A являются также экзмеплярами B", x является также экземпляром B. Поскольку "ни один экзмепляр B не является экземпляром A", то x не является экземпляром A. Получили противоречие, так как x не может одновременно являться экземпляром A и не являться экземпляром A. Следовательно, из предположения, что A наследует B, следует, что не существует ни одного экземпляра A. Хм...

Вышеприведенное рассуждение верно естественно только если "наследование — это расширение понятия, когда все экзмепляры A являются также экзмеплярами B, но ни один экзмепляр B не является экземпляром A".
Re[2]: И эти люди...
От: igna Россия  
Дата: 03.03.07 23:13
Оценка:
Здравствуйте, McSeem2, Вы писали:

MS>...утверждают, что парадигма наследования имеет хоть какую-то практическую пользу?!


Ась? Какие люди "утверждают, что парадигма наследования имеет хоть какую-то практическую пользу"?
Re[3]: И эти люди...
От: igna Россия  
Дата: 03.03.07 23:30
Оценка: +1
Здравствуйте, _nn_, Вы писали:

__>interface ISquare : IRectangle , IRhombus


Вот эта возможность унаследовать ISquare от IRectangle обусловлена отсутствием в последнем методов вроде SetWidth и SetHeight.

Так что классы ли, интерфейсы ли, наследовать квадрат от прямоугольника можно только если оба неизменны (как в математике).
Re[3]: И все-таки квадрат это прямоугольник
От: VoidEx  
Дата: 04.03.07 14:01
Оценка: -4
Здравствуйте, igna, Вы писали:

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


I>Предположим, что A наследует B, а x является экземпляром A. Поскольку "все экзмепляры A являются также экзмеплярами B", x является также экземпляром B. Поскольку "ни один экзмепляр B не является экземпляром A", то x не является экземпляром A. Получили противоречие, так как x не может одновременно являться экземпляром A и не являться экземпляром A. Следовательно, из предположения, что A наследует B, следует, что не существует ни одного экземпляра A. Хм...


Вы прекрасно поняли, о чем я говорил, придираться к формулировке можете перед зеркалом.
Re[4]: И все-таки квадрат это прямоугольник
От: FDSC Россия consp11.github.io блог
Дата: 04.03.07 14:53
Оценка:
Здравствуйте, VoidEx, Вы писали:

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


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


I>>Предположим, что A наследует B, а x является экземпляром A. Поскольку "все экзмепляры A являются также экзмеплярами B", x является также экземпляром B. Поскольку "ни один экзмепляр B не является экземпляром A", то x не является экземпляром A. Получили противоречие, так как x не может одновременно являться экземпляром A и не являться экземпляром A. Следовательно, из предположения, что A наследует B, следует, что не существует ни одного экземпляра A. Хм...


VE>Вы прекрасно поняли, о чем я говорил, придираться к формулировке можете перед зеркалом.


Вы сказали чушь откровенную. Настолько, что я так и не смог написать вам ответ с опровержением. Так что спасибо igna за то, что выразил мои мысли.
Re[2]: И все-таки квадрат это прямоугольник
От: Smal Россия  
Дата: 04.03.07 15:13
Оценка: 1 (1)
Здравствуйте, Владек, Вы писали:

В>В математическом смысле вы правы — можно ввести такую бинарную операцию над элементами множества, что результат её выполнения не будет принадлежать исходному множеству. Это свойство имеет название, но я его забыл. Пример: операция деления натуральных чисел, результат не всегда является натуральным числом (1/2=0.5).

В общем-то бинарная операция по определению замкнутая (т.е. является отображением M x M -> M). Другими словами, деление на множестве натуральных чисел не бинарная операция
С уважением, Александр
Re[2]: И все-таки квадрат это прямоугольник
От: igna Россия  
Дата: 04.03.07 16:49
Оценка:
Здравствуйте, VoidEx, Вы писали:

VE>Все здесь неприлично. Наследование — это расширение понятия, когда все экзмепляры A являются также экзмеплярами B, но ни один экзмепляр B не является экземпляром A.

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

Можно ли сконструировать пример, демонстрирующий "неприличность" кода, который я привел в первом сообщении
Автор: igna
Дата: 03.03.07
этой темы?
Re[3]: И эти люди...
От: Alxndr Германия http://www.google.com/profiles/alexander.poluektov#buzz
Дата: 04.03.07 19:16
Оценка:
Здравствуйте, igna, Вы писали:

MS>>...утверждают, что парадигма наследования имеет хоть какую-то практическую пользу?!


I>Ась? Какие люди "утверждают, что парадигма наследования имеет хоть какую-то практическую пользу"?


Ммм, ну я, например
Re[4]: И эти люди...
От: _nn_ www.nemerleweb.com
Дата: 04.03.07 19:45
Оценка:
Здравствуйте, igna, Вы писали:

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


I>
__>>interface ISquare : IRectangle , IRhombus
I>


I>Вот эта возможность унаследовать ISquare от IRectangle обусловлена отсутствием в последнем методов вроде SetWidth и SetHeight.


I>Так что классы ли, интерфейсы ли, наследовать квадрат от прямоугольника можно только если оба неизменны (как в математике).


А чем так плохи неизменяемые объекты ?

Можно изменять введя дополнительные интерфейсы IChangeRectange, IChangeSquare
http://rsdn.nemerleweb.com
http://nemerleweb.com
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.