Re[9]: protected наследование
От: MaximE Великобритания  
Дата: 13.05.03 09:29
Оценка:
Здравствуйте, Дмитрий Наумов, Вы писали:

>Вот именно что в данном. Если представить что у агрегируемых классов имеется на всех сотня открытых методов, которые надо предоставить (expose) клиентам и каких либо других противопоказаний к наследованию у вас нет, то что вы выберете — агрегацию и написать сотню методов для делегации или закрытое наследование?


Напишу так:

////////////////////////////////////////
// интерфейсы

struct Alice {};
struct Bob {};
struct Carol {};

struct Trent
{
    virtual Alice& GetAlice() = 0;
    virtual Bob& GetBob() = 0;
    virtual Carol& GetCarol() = 0;
};

////////////////////////////////////////
// реализация

class AliceImpl : public Alice {};
class BobImpl : public Bob {};
class CarolImpl : public Carol {};

class TrentImpl : public Trent
{
public:
    Alice& GetAlice() { return a_; }
    Bob& GetBob() { return b_; }
    Carol& GetCarol() { return c_; }

private:
    AliceImpl a_;
    BobImpl b_;
    CarolImpl c_;
};
Re[13]: protected наследование
От: MaximE Великобритания  
Дата: 13.05.03 09:36
Оценка:
Здравствуйте, Дмитрий Наумов, Вы писали:

ДН>Потому как, его послушать, мой Car все таки has a wheel, несмотря на то, что сделано через наследование. ИМХО зря он тут ввел всякие application domain, implementation domain — толком ничего и не сказал.


So you couldn't say a Car IS-IMPLEMENTED-IN-TERMS-OF Wheels. A Car HAS Wheels.


Насколько я понимаю, он пишет, что "has-a" и "implemented in terms of" альтернативные вещи. Нельзя сказать, что "has-a" реализовано как "implemented in terms of".
Re[10]: protected наследование
От: Дмитрий Наумов  
Дата: 13.05.03 09:39
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Здравствуйте, Дмитрий Наумов, Вы писали:


>>Вот именно что в данном. Если представить что у агрегируемых классов имеется на всех сотня открытых методов, которые надо предоставить (expose) клиентам и каких либо других противопоказаний к наследованию у вас нет, то что вы выберете — агрегацию и написать сотню методов для делегации или закрытое наследование?


ME>Напишу так:


ME>
ME>////////////////////////////////////////
ME>// интерфейсы

ME>struct Alice {};
ME>struct Bob {};
ME>struct Carol {};

ME>struct Trent
ME>{
ME>    virtual Alice& GetAlice() = 0;
ME>    virtual Bob& GetBob() = 0;
ME>    virtual Carol& GetCarol() = 0;
ME>};

ME>////////////////////////////////////////
ME>// реализация

ME>class AliceImpl : public Alice {};
ME>class BobImpl : public Bob {};
ME>class CarolImpl : public Carol {};

ME>class TrentImpl : public Trent
ME>{
ME>public:
ME>    Alice& GetAlice() { return a_; }
ME>    Bob& GetBob() { return b_; }
ME>    Carol& GetCarol() { return c_; }

ME>private:
ME>    AliceImpl a_;
ME>    BobImpl b_;
ME>    CarolImpl c_;
ME>};

ME>


Тоже вариант. Пробовал я так тоже, но, чистое ИМХО, где то в глубине души что то мне не понравилось давать полный доступ к членам класса на прямую. Даже не помню, что не понравилось...

P.S. Может то, что управление временем жизни внешнего объекта (TrentImpl) уходит в сторону, а у вас на руках остается ссылка на его(может уже "мертвого") член класса.
... << RSDN@Home 1.0 beta 6a >>
Re[14]: protected наследование
От: Дмитрий Наумов  
Дата: 13.05.03 09:47
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>

ME>So you couldn't say a Car IS-IMPLEMENTED-IN-TERMS-OF Wheels. A Car HAS Wheels.


ME>Насколько я понимаю, он пишет, что "has-a" и "implemented in terms of" альтернативные вещи. Нельзя сказать, что "has-a" реализовано как "implemented in terms of".


Думаю, все же, это не альтернатива, а ... как божий дар и яичница.
class Engine {};
class EngineObject : public Engine {};
class Car : private EngineObject {};


Если класс EngineObject предоставляет некие методы, которые нужны чисто для реализации, типа InitAllMyVarsWithDefaults, и этот объект/его методы мы не "показываем" клиенту (то есть ему он нафиг не нужен, его могло бы и не быть, просто код мы так пишем), то
Car is-implemented-in-terms-of EngineObject.

P.S. Но можно ли сказать что в этом случае Car has a Engine?
P.P.S. Я заодно по тем ссылкам почитал что Мейерс с Саттером думают про защищенное наследование — они сами толком не знают как его назвать
... << RSDN@Home 1.0 beta 6a >>
Re[14]: protected наследование
От: Дмитрий Наумов  
Дата: 13.05.03 09:55
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Насколько я понимаю, он пишет, что "has-a" и "implemented in terms of" альтернативные вещи. Нельзя сказать, что "has-a" реализовано как "implemented in terms of".


Я бы даже сказал так — отношение между Derived и Base объектами, связанными закрытым наследованием может выражаться как "has-a", так и "implemented-in-terms...", взависимости от того, в каком домене находится Base.

Простой пример — если Base это Engine, то можно сказать что Derived(Car) has a Engine. Если же Base это какой то вспомогательный объект, о котором клиент НЕ ЗНАЕТ, то он не может так сказать. А мы можем сказать — Derived implemented in terms of EngineSupplementaryObject.
... << RSDN@Home 1.0 beta 6a >>
Re[11]: protected наследование
От: MaximE Великобритания  
Дата: 13.05.03 09:56
Оценка:
Здравствуйте, Дмитрий Наумов, Вы писали:

ДН>Тоже вариант. Пробовал я так тоже, но, чистое ИМХО, где то в глубине души что то мне не понравилось давать полный доступ к членам класса на прямую. Даже не помню, что не понравилось...


Никто и не дает доступ к членам. Даем только интерфейс.

ДН>P.S. Может то, что управление временем жизни внешнего объекта (TrentImpl) уходит в сторону, а у вас на руках остается ссылка на его(может уже "мертвого") член класса.


Здесь мы даем лишь ссылку на часть агрегата. Такая семантика говорит, что Trent не собирается разделять или передавать владение.
Re[13]: protected наследование
От: VanKir  
Дата: 13.05.03 10:03
Оценка: 8 (1) +1
Здравствуйте, Дмитрий Наумов, Вы писали:

ДН>Здравствуйте, MaximE, Вы писали:


ME>http://www.google.com/search?sourceid=navclient&amp;ie=UTF-8&amp;oe=UTF-8&amp;q=c%2B%2B+%22is%2Da%22+%22implemented+in+terms+of%22


ДН>По ссылке:

ДН>

ДН>Bill Venners: Please differentiate HAS-A and IS- IMPLEMENTED-IN-TERMS-OF.

ДН>Scott Meyers: When you write software, you deal with two worlds. You deal with the world you want to model, the outside world. You also deal with a world that exists only inside the software, which involves just getting the code to work. HAS-A corresponds to something in the real world. A Car HAS Wheels or a Person HAS Friends. HAS-A corresponds to the application domain. IS-IMPLEMENTED-IN-TERMS-OF never exists in the real world; it is part of the implementation domain. So you couldn't say a Car IS-IMPLEMENTED-IN-TERMS-OF Wheels. A Car HAS Wheels. But you could say the ParkingLot IS-IMPLEMENTED-IN-TERMS-OF a List. There's no List in the real world. The List only exists inside the software. So HAS-A is a relationship between classes that exists in the application domain. IS-IMPLEMENTED-IN-TERMS-OF is a relationship between classes that exists in the implementation domain.

ДН>Bill Venners: That's great. That clarifies it for me.

ДН>Scott Meyers: It took me a few years to figure that out myself, actually.


ДН>Видно мои "a few years" еще не прошли, потому как я нифига не понял...

ДН>Потому как, его послушать, мой Car все таки has a wheel, несмотря на то, что сделано через наследование. ИМХО зря он тут ввел всякие application domain, implementation domain — толком ничего и не сказал.

Если я правильно понял, то суть этой заметки в том, что нельзя путать эти два понятия, тк одно (has-a) показывает отношение между объектами в реальном мире (HAS-A corresponds to something in the real world) а другое (IS-IMPLEMENTED-IN-TERMS-OF) показывает отношение между объектами, которые не существуют в реальном мире и относятся только к части реализации... IMHO разумеется
Re[9]: protected наследование
От: Дмитро  
Дата: 13.05.03 10:05
Оценка:
Здравствуйте, Дмитрий Наумов, Вы писали:

ДН>Вот именно что в данном. Если представить что у агрегируемых классов имеется на всех сотня открытых методов, которые надо предоставить (expose) клиентам и каких либо других противопоказаний к наследованию у вас нет, то что вы выберете — агрегацию и написать сотню методов для делегации или закрытое наследование?


Если методы надо предоставить клиентам, то закрытое -- врядли.

А что касается ответа на вопрос: "зачем нужно protected наследование?", то можно ответить, что это просто фича C++. Модификаторы доступа при наследовании определяют уровень доступа к базовому подобъекту. Если исходить из того, что базовые подобъекты агрегируются так же как и члены-данные, то это кажется вполне логичным, что при наследовании можно задавать private, protected или public. Кстати, в других языках этого нет.

Если ты разрабатываешь некий класс B, который наследуется от некого класса A, и тебе нужно, чтобы только предки класса B знали о своем родстве с A, т.е. могли доступиться к public и protected полям и методам класса A, то наследуй B от A как protected.

Мне кажется, что то, что private наследование реализует отношение has-a, было придумано после того, как это самое private наследование появилось. Строго говоря, и public наследование не всегда можно отождествлять с отношением is-a. Так, например, круг является эллипсом, но наследовать круг от эллипса -- идея не очень удачная. Точно так же и наследовать класс RedFigure от класса Figure, у которой есть атрибут color. Так что подходить к проектированию иерархий классов нужно с оглядкой на язык, на котором это будет реализовано. И предствлять, какие выгоды даст то или иное наследование.

--
Дмитрий
--
Дмитрий
Re[15]: protected наследование
От: MaximE Великобритания  
Дата: 13.05.03 10:06
Оценка:
Здравствуйте, Дмитрий Наумов, Вы писали:

ДН>Здравствуйте, MaximE, Вы писали:


ME>>Насколько я понимаю, он пишет, что "has-a" и "implemented in terms of" альтернативные вещи. Нельзя сказать, что "has-a" реализовано как "implemented in terms of".


ДН>Я бы даже сказал так — отношение между Derived и Base объектами, связанными закрытым наследованием может выражаться как "has-a", так и "implemented-in-terms...", взависимости от того, в каком домене находится Base.


ДН>Простой пример — если Base это Engine, то можно сказать что Derived(Car) has a Engine. Если же Base это какой то вспомогательный объект, о котором клиент НЕ ЗНАЕТ, то он не может так сказать. А мы можем сказать — Derived implemented in terms of EngineSupplementaryObject.


На мой взгляд, не стоит усердствовать со связыванием наследованием концептуально разных сущностей при проетировании.

Закрытое наследование может быть уместно для оптимизации, например закрыто отнаследовать vector от allocator, т.к. обычно allocator не содержит членов, чтобы компилятор мог применить empty base optimization, вместо того, чтобы хранить allocator в vector по значению. (возможно не самый удачный пример).
Re[5]: protected наследование
От: Аноним  
Дата: 13.05.03 10:07
Оценка: 10 (2) +1
Здравствуйте, Михаил Можаев, Вы писали:

ММ>Ну и как воспользоваться тем, что VasyaPupkin "is-a" SexualManiac ?

ММ>Все же более логично пользоваться закрытым наследованием для выражения "has-a" (Вася имеет соответствующие наклонности) или, действительно, "is-implemented-in-terms-of". А от "is-a" остается только скрытая связь, которой нельзя воспользоваться.

А лучше переписать с использованием классов-политик. Или признаков.

Наивная реализация:

template<
    class sexual_traits,
    class medical_traits,
    class stomach_traits,
    class look_traits,
    class mind_traits,
    class character_traits
>
class human :
    private sexual_traits::mania,
    protected medical_traits::inherited_disease_list
{
    // ...
};

class vasya_pupkin :
    public human< sexual_maniac_traits, ... >
Re[14]: protected наследование
От: Дмитрий Наумов  
Дата: 13.05.03 10:20
Оценка:
Здравствуйте, VanKir, Вы писали:

VK>Если я правильно понял, то суть этой заметки в том, что нельзя путать эти два понятия, тк одно (has-a) показывает отношение между объектами в реальном мире (HAS-A corresponds to something in the real world) а другое (IS-IMPLEMENTED-IN-TERMS-OF) показывает отношение между объектами, которые не существуют в реальном мире и относятся только к части реализации... IMHO разумеется


Так вывод? Car <....> Engine (подставьте нужное)
... << RSDN@Home 1.0 beta 6a >>
Re[10]: protected наследование
От: Михаил Можаев Россия www.mozhay.chat.ru
Дата: 13.05.03 10:28
Оценка:
Здравствуйте, Дмитро, Вы писали:

Д>Так, например, круг является эллипсом, но наследовать круг от эллипса -- идея не очень удачная.


Просто кроме "is-a" при наследовании обычно происходит расширение функциональности. А тут скорее наоборот. Тогда уж лучше отнаследовать эллипс от круга, добавив второй радиус. Хотя это уже нарушение логики...
... << RSDN@Home 1.0 beta 6a >>
Re[15]: protected наследование
От: VanKir  
Дата: 13.05.03 10:43
Оценка:
Здравствуйте, Дмитрий Наумов, Вы писали:

ДН>Здравствуйте, VanKir, Вы писали:


VK>Если я правильно понял, то суть этой заметки в том, что нельзя путать эти два понятия, тк одно (has-a) показывает отношение между объектами в реальном мире (HAS-A corresponds to something in the real world) а другое (IS-IMPLEMENTED-IN-TERMS-OF) показывает отношение между объектами, которые не существуют в реальном мире и относятся только к части реализации... IMHO разумеется


ДН>Так вывод? Car <....> Engine (подставьте нужное)

HAS-A IMHO
Re[16]: protected наследование
От: VanKir  
Дата: 13.05.03 10:53
Оценка:
Здравствуйте, VanKir, Вы писали:

VK>Здравствуйте, Дмитрий Наумов, Вы писали:


ДН>Здравствуйте, VanKir, Вы писали:


VK>Если я правильно понял, то суть этой заметки в том, что нельзя путать эти два понятия, тк одно (has-a) показывает отношение между объектами в реальном мире (HAS-A corresponds to something in the real world) а другое (IS-IMPLEMENTED-IN-TERMS-OF) показывает отношение между объектами, которые не существуют в реальном мире и относятся только к части реализации... IMHO разумеется


ДН>Так вывод? Car <....> Engine (подставьте нужное)

VK>HAS-A IMHO
точнее не так, на первом этапе проектирования, когда вы оперируете понятиями реального мира это будет has-a а дальше, когда вы уже будите работать с классами и тд (те программными сущьностями) это уже будет IS-IMPLEMENTED-IN-TERMS-OF
Re[15]: protected наследование
От: limax Россия http://mem.ee
Дата: 13.05.03 10:59
Оценка: 15 (2)
Здравствуйте, Дмитрий Наумов, Вы писали:
ДН>Так вывод? Car <....> Engine (подставьте нужное)

На мой взгляд всё просто: считаешь ли ты возможным применять методы Engine или Wheel к сущности Car?
Если да, то is-a или is-implemented-in-terms-of, если нет, то has-a
На примере с колесом: можешь ли ты сдуть, надуть машину? Вряд ли , значит has-a.
С двигателем: завести, заглушить — вроде вполне подходит. Но что делать, когда нужно подать питание от аккумулятора, подать бензин и масло, охладить, наконец, заменить к чертям собачим? Вывод: тоже has-a.
Have fun: Win+M, Ctrl+A, Enter
Re[16]: protected наследование
От: limax Россия http://mem.ee
Дата: 13.05.03 11:06
Оценка:
Добавка: раз private, значит все эти действия должна производить машина или её доверенные лица (friends). Но всё равно надуться машина никак не может.
Have fun: Win+M, Ctrl+A, Enter
Re[10]: protected наследование
От: Павел Кузнецов  
Дата: 13.05.03 11:40
Оценка:
Здравствуйте, Дмитро, Вы писали:

Д> Строго говоря, и public наследование не всегда можно

Д> отождествлять с отношением is-a. Так, например, круг является
Д> эллипсом, но наследовать круг от эллипса -- идея не очень удачная.

Не нужно смешивать житейское понятие "является" с термином "is-a",
обозначающим отношение между двумя классами. Существование последнего
определяется критерием замещения Барбары Лисков. В этом смысле public
наследование совершенно четко соответствует отношению "is-a".
Posted via RSDN NNTP Server 1.5 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[16]: protected наследование
От: Дмитрий Наумов  
Дата: 13.05.03 11:47
Оценка:
Здравствуйте, limax, Вы писали:

L>Здравствуйте, Дмитрий Наумов, Вы писали:

ДН>>Так вывод? Car <....> Engine (подставьте нужное)

L>На мой взгляд всё просто: считаешь ли ты возможным применять методы Engine или Wheel к сущности Car?

L>Если да, то is-a или is-implemented-in-terms-of, если нет, то has-a
L>На примере с колесом: можешь ли ты сдуть, надуть машину? Вряд ли , значит has-a.
L>С двигателем: завести, заглушить — вроде вполне подходит. Но что делать, когда нужно подать питание от аккумулятора, подать бензин и масло, охладить, наконец, заменить к чертям собачим? Вывод: тоже has-a.

Вы сказали ПРИМЕРНО как и я думаю. Но все же и Мейерс, и Саттер и я думаем что Car has an Engine. И, имхо, примеривать возможность "сдуть, надуть" не совсем корректно. Какой я сделал вывод из той статьи, что цитировал выше — если базовая сущность находится в application domain, пользователь о ней знает, то говорим has-a. Если же это детали реализации, то implemented.
... << RSDN@Home 1.0 beta 6a >>
Re[16]: protected наследование
От: dkon  
Дата: 13.05.03 12:04
Оценка:
Здравствуйте, MaximE, Вы писали:

ДН>Простой пример — если Base это Engine, то можно сказать что Derived(Car) has a Engine. Если же Base это какой то вспомогательный объект, о котором клиент НЕ ЗНАЕТ, то он не может так сказать. А мы можем сказать — Derived implemented in terms of EngineSupplementaryObject.


ME>На мой взгляд, не стоит усердствовать со связыванием наследованием концептуально разных сущностей при проетировании.


ME>Закрытое наследование может быть уместно для оптимизации, например закрыто отнаследовать vector от allocator, т.к. обычно allocator не содержит членов, чтобы компилятор мог применить empty base optimization, вместо того, чтобы хранить allocator в vector по значению. (возможно не самый удачный пример).


рекомендуется использовать закрытое наследование, если необходимо переопределить виртуальные функции объекта (для реализации паттерна темплейтного метода, например).
Re[11]: protected наследование
От: Дмитро  
Дата: 13.05.03 12:27
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Здравствуйте, Дмитро, Вы писали:


Д> Строго говоря, и public наследование не всегда можно

Д> отождествлять с отношением is-a. Так, например, круг является
Д> эллипсом, но наследовать круг от эллипса -- идея не очень удачная.

ПК>Не нужно смешивать житейское понятие "является" с термином "is-a",

ПК>обозначающим отношение между двумя классами. Существование последнего
ПК>определяется критерием замещения Барбары Лисков. В этом смысле public
ПК>наследование совершенно четко соответствует отношению "is-a".

Это зависит от того, как определять отношение "is-a". К слову, критерий замещения Барбары не может служить определением отношения "is-a", поскольку этот термин там отсутствует вовсе. По крайней мере в этом варианте:

Liskov Substitution Principle: Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.


А вот с тем, что житейское понятие "является" -- это не public наследование (не всегда они совпадают), я абсолютно согласен.

--
Дмитрий
--
Дмитрий
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.