int get_var1(void)
{
return var1;
}
////////////////////////////////
void set_var1(int _var)
{
var1 = _var;
}
private vs public variable
Код:
Так, что безопасней? Ведь, когда пишешь прогу ты же контролируешь что и где используется.
Советую почитать что-нибудь по ООП.
Вопросы отпадуд сами собой при изучении термина "инкапсуляция".
Советую почитать что-нибудь по ООП.
Вопросы отпадуд сами собой при изучении термина "инкапсуляция".[/QUOTE]
Можешь пример привести, где мне может как-то помешать объявление переменных как public
Я приведу примеры с private-членами, а как может помешать объявление этих членов, как public, ты уж подумай сам.
Пример 1:
Код:
class String
{
public:
String(const char* szStr) {
str = new char[strlen szStr];
strcpy(stzr, szStr);
}
~String() {
delete[] str;
}
private:
char* str;
};
{
public:
String(const char* szStr) {
str = new char[strlen szStr];
strcpy(stzr, szStr);
}
~String() {
delete[] str;
}
private:
char* str;
};
Пример 2:
Код:
class File
{
public:
File() :opened(false) {}
~File() {
if ( isOpened() ) {
close();
}
}
void open() {
.......
opened = true;
}
void close() {
.......
opened = false;
}
bool isOpen() {
retrun opened;
}
private:
bool opened;
};
{
public:
File() :opened(false) {}
~File() {
if ( isOpened() ) {
close();
}
}
void open() {
.......
opened = true;
}
void close() {
.......
opened = false;
}
bool isOpen() {
retrun opened;
}
private:
bool opened;
};
Пример 3:
Код:
template<typename T>
class Stack
{
public:
void push(const T& val) {
container.push_back(val);
}
T pop() {
T val = container.back();
container.pop_back();
return val;
}
private:
std::vector<T> container;
};
class Stack
{
public:
void push(const T& val) {
container.push_back(val);
}
T pop() {
T val = container.back();
container.pop_back();
return val;
}
private:
std::vector<T> container;
};
Дело не в этом. Начитался я книжек и знаю про инкопсуляцию, и про полиморфизм и про наследование и др. аспекты объектно - ориентированного программирования. Просто каждый вызов функции - это лишняя задержка. Зачем они, если можно напрямую. Я согласен насчет конструкторов или, если нужно обработать член класса представленный объектом, динамическим объектом, массивом, строкой, но зачем на каждую переменную пусть даже int - овсую создавать функцию установки и возврата значения даже если она нужна только для внутренних нужд. Впрочем каждый волен кодить по своему. Но для поддержания хорошего стиля рекомендуется придерживаться этой методологии (говорят те же книги). Вопрос - зачем?
гыг.. попробуй это понять с помощью такой аналогии : зачем тебе каждый раз копаться во внутренностях , ну скажем телевизора, и крутить там какой нить переменный резистор пытясь понять какое сопротивление надо выставить что бы посмотреть тот или иной канал, ведь можно просто нажать на лицевой панели или пульте управления кнопку с нужным номером канала, и вместо того что бы тратить уйму времени на тюнинг :) переменного резистора, просто наслаждаться :) избранным каналом. В книге Гради Буча про ООП есть хорошая карикатура на эту тему.
Код:
int get_var1(void)
{
return var1;
}
////////////////////////////////
void set_var1(int _var)
{
var1 = _var;
}
{
return var1;
}
////////////////////////////////
void set_var1(int _var)
{
var1 = _var;
}
Так, что безопасней? Ведь, когда пишешь прогу ты же контролируешь что и где используется.[/QUOTE]
твой пример, слишком прост, в реальных классах, используется несколько переменных. каждая переменная имеет имеет свое множество значений, и декартово произведение этих множеств, составляет множество возможных состояний объектов этого класса. однако на практике только некоторое подмножество этого множества является корректным для этого класса при отображении в его предметную область. для удержания состояния в этом подмножестве изменение происходит по определенным правилам , которые реализуются методами этого класса. изменяя же данные напрямую , мы можем , то есть имеем принципиальную возможность, ввести объект в некорректное состояние. даже если ты разрабытваешь программу один, и на данном этапе все контролируешь, то с ростом сложности системы, то бишь с развитием программы, кол-во перемменых вырастет, и контролировать будет все сложнее и сложнее. не говоря уже о коллективной разработке.
Если set/get функции прописать (реализовать) в описании класса, то компилятор будет подставлять их код в место "вызова" - вот и твоя оптимизация.
Это называется inline-методами и их необязательно определять в определении класа, достаточно указать слово inline.
В идеале каждый класс должен представлять из себя черный ящик. Класс предоставляет только методы для работы с пданными класса, но как класс преобразует данные должно быть скрыто.
Представь ситуацию:
1. У тебя есть класс, в котором открытая строковая переменная.
2. Ты по всей своей программе, что ей напрямую присваиваешь.
3. Бац! Появилась необходимость изменить алгоритм работы с переменной, например, надо автоматом добавлять расширение.
И что? Ты будешь лазить по всему коду и добавлять код для добавления расширения?
Если оформить обращение к строке через метод, то достаточно изменить алгоритм в методе, а остальная часть кода даже этого и не заметит.
[quote=Sagittarius]Я бы порекомендовал прочитать книгу "Совершенный код" Стива Макконнелла ...[/quote]
Спосибо всем. Немного вправили мне мозги.
Практически всё уже сказано, просто подведу краткий итог: set/get и объявление переменной как private нужно прежде всего для того, чтобы защитить тебя же от твоих собственных ошибок, а также защитить твой класс от несанкционированного изменения пользователем (т. е. человеком, который будет пользоваться твоим классом). Впрочем, как и множество других возможностей С++ и вообще ООП. Потому код, написанный в соответствии с общепринятыми правилами, и называется "безопасным". А обсуждаемый в теме вопрос можно отнести к принципу "разделяй интерфейс и реализацию, а при проектировании класса перво-наперво определись с интерфейсом, чтобы потом его не менять".
А насчет
[QUOTE=Oxaid]Просто каждый вызов функции - это лишняя задержка. Зачем они, если можно напрямую.[/QUOTE]
- объявляй функцию как inline, и никаких задержек.
Практически всё уже сказано, просто подведу краткий итог: set/get и объявление переменной как private нужно прежде всего для того, чтобы защитить тебя же от твоих собственных ошибок.... [/QUOTE]
я бы советовал вместо private использовать protected. лично у меня из собственного опыта работы складывается впечатление что private придумали для того что бы скрывать кривости реализации. не использую private вообще уже несколько лет :D
http://education.aspu.ru/page.php?id=48[/QUOTE]
классные ссылки... то че то они не фунциклируют... а почитатать сильна хочется
[QUOTE=OlgaKr]
классные ссылки... то че то они не фунциклируют... а почитатать сильна хочется
А я бы не рекомендовал использовать protected.
IMHO, protected идет вразрез принципам ООП, а применение во многих случаях - признак плохой архитектуры.
IMHO, protected идет вразрез принципам ООП, а применение во многих случаях - признак плохой архитектуры.[/QUOTE]
гыг... вот раскажика здеся поподробнее почему это protected признак плохой архитектуры? я думаю начать тебе надо с определения понятия плохая архитектура. :D если все таки придумаешь что ответить то сразу напиши как добавить в производном классе функцию, расширяющую функциональность базового класса но действующую на том же множестве переменных что и базовый класс + зависимость от своей дополнительно введенной переменной. я считаю, что использование protected заставляет программиста не только красиво писать public-интерфейс но и внятно реализовывать этот интерфейс, в частности выбирая понятные имена для protected-перемменных, так как эти переменные могут быть задействованы в производном классе другим программистом. девиз одного из знакомых мне типа коол-леад-программиста что "главное что б интерфейс был красивым - а реализация может идти через задницу" - для меня теперь неприемлем.
Код:
class Tiger
{
public:
Krolik( int x, int y )
{
// алгоритм преследования кролика в точке x,y
while ( ... ) { if ( left ) nogi.left()
else if ( right ) nogi.right(); }
// догнал
chelusti.zaxvat();
}
protected:
chelusti _chelusti;
nogi _nogi;
};
class FlyTiger : public Tiger
{
public:
Krolik( int x, int y )
{
// на взлет:
nogi.podzhat(); // команда - поджать ноги - для лучшей обтекаемости в полете. if nogi is private - compiler error.
// алгоритм преследования кролика в точке x,y
while ( ... ) { if ( left ) wing_right.vzmax()
else if ( right ) wing_left.vzmax(); }
// догнал
chelusti.zaxvat();
}`
protected:
Wing wing_left, wing_right;
};
{
public:
Krolik( int x, int y )
{
// алгоритм преследования кролика в точке x,y
while ( ... ) { if ( left ) nogi.left()
else if ( right ) nogi.right(); }
// догнал
chelusti.zaxvat();
}
protected:
chelusti _chelusti;
nogi _nogi;
};
class FlyTiger : public Tiger
{
public:
Krolik( int x, int y )
{
// на взлет:
nogi.podzhat(); // команда - поджать ноги - для лучшей обтекаемости в полете. if nogi is private - compiler error.
// алгоритм преследования кролика в точке x,y
while ( ... ) { if ( left ) wing_right.vzmax()
else if ( right ) wing_left.vzmax(); }
// догнал
chelusti.zaxvat();
}`
protected:
Wing wing_left, wing_right;
};
В хорошей архитектуре количество взаимосвязей должно сводиться к минимуму, чтобы не получалось запутанных клубков.
Продолжая спонтанный ликбез, расскажу, что любую сущность можно логически разделить на интерфейс и скрывающуюся за ним реализацию. Наверное, ты невнимательно слушал своего друга, который, видимо, говорил "главное - предоставить полноценный, но не излишний интерфейс, а реализация должна быть скрыта от пользователя и не имеет для пользователя решающего значения". Это одно из правил ООП (инкапсуляция) и более категоричное правило Парнаса: пользователь ничего не должен знать о реализации и опереровать лишь интерфейсом.
Для чего это делается обсуждалось уже в этом топике, я повторяться не буду, лучше обратись к умным книгам.
Теперь что касается твоего примера.
Ты сам то понимаешь, что обращаясь напрямую к реализации базового объекта, ты нарушаешь его концептуальную целостность и вводишь множество неявных взаимосвязей? В твоем случае невозможно изменение базового объекта независимо от наследников. Это признак плохой архитектуры.
Почему так получилось? Потому, что не был продуман интерфейс базового объекта. Либо был предоставлен не полноценный интерфейс, либо был выбран неправильный фокус создания интерфейса, а может и самого класса. В твоем примере базовый класс Tiger определяет какую сущность? Если движущийся объект, то надо было сосредоточиться на движении: stepLeft(), stepRight() и т.п. При этом наследник уже не задумывается о том как именно передвигается тигр, на лапах или на крыльях. Если же выбор способа передвижения определяется наследником, то и определять этот тип надо в наследнике. Либо базовый класс может иметь лишь ссылку на универсальный интерфейс движителя, а сам движитель задается в потомке или при конструировании объекта.
В твоем примере базовый класс, агрегируя ноги, не предоставил интерфейс для управления ими. Значит, изначально пользователь не должен был сосредотачиваться на типе движителя. Далее, например, ноги могли бы быть заменены в базовом классе на крылья, в крылья лучше не поджимать... :D
В твоем примере, если мы заменим ноги на крылья, нам придется менять имена в наследниках и даже реализацию наследников. Такая цепочка изменений - признак плохой архитектуры.
Если же изначально предполагалось, что тигр двигается только на лапах, которые можно поджимать, должен был быть предоставлен интерфейс для такой операции. Он не был предоставлен, а значит интерфейс оказался не полноценным, а это признак плохой архитектуры. Но на начальном этапе это вполне нормально,- интерфейс обычно расширяется итерационно.
Если твой пример спроецировать на лошадь (базовый класс) со всадником (наследник), то получается, что наездник должен сам дергать за сухожилия ноги лошади, а не управлять движением через интерфейс "стремя". :D
Одним словом, я с трудом могу представить (но все же могу, хотя это очень специфичные единичные случаи), где нужен protected.
В твоем примере он точно не нужен, а наоборот запутывает всю картину.
2 Green: ну ты и зажёг
В хорошей архитектуре количество взаимосвязей должно сводиться к минимуму, чтобы не получалось запутанных клубков.
Продолжая спонтанный ликбез, расскажу, что любую сущность можно логически разделить на интерфейс и скрывающуюся за ним реализацию. Наверное, ты невнимательно слушал своего друга, который, видимо, говорил "главное - предоставить полноценный, но не излишний интерфейс, а реализация должна быть скрыта от пользователя и не имеет для пользователя решающего значения". Это одно из правил ООП (инкапсуляция) и более категоричное правило Парнаса: пользователь ничего не должен знать о реализации и опереровать лишь интерфейсом.
Для чего это делается обсуждалось уже в этом топике, я повторяться не буду, лучше обратись к умным книгам..[/QUOTE]
это все конечно замечательно, но здесь нет ни слова о том почему protected признак плохой архитектуры. это раз. а вот те два - не надо доводить принцип инкапсуляции до идиотизма. инкапсуляция впервую очередь нужна для сокрытия деталей реализации от пользователя класса. то есть отношения использования класса. однако при отношении наследования от класса детали должны быть открыты, так как в данном случае мы являемся разработчиком класса а не его пользователем. другими словами инкапсуляция уместна при отношении использования, и не уместна при отношения наследования.
[QUOTE=Green]
Теперь что касается твоего примера.
Ты сам то понимаешь, что обращаясь напрямую к реализации базового объекта, ты нарушаешь его концептуальную целостность и вводишь множество неявных взаимосвязей? В твоем случае невозможно изменение базового объекта независимо от наследников. Это признак плохой архитектуры.[/QUOTE]
гыг вот интересно ты что предлагаешь здеся посередине утомительного процесса разработки оторвать тигру ноги или челюсти ? че то нелогично. у всех тигров есть ноги и челюсти. и только у некоторых из них крылья. при этом они сохраняют свойства предка - имеют челюсти и ноги. именно поэтому они выделены в отдельный класс. таким образом показано что классы отличаются не только реализацией виртуальных методов но и таким свойством как полимофризм - то есть разное строение ( интерпритируется как различный набор переменных ). перевод слова полиморфизм получается практически дословный. однако так как теперь у данной разнвиднсти тигров есть крылья которые дают большое преимущество при преследовании, что дает нам право определить тигру новую стратегию преследования кролика, основанную на крыльях. достигаем этого посредством переопределения виртуального метода Krolik.
[QUOTE=Green]
Почему так получилось? Потому, что не был продуман интерфейс базового объекта. Либо был предоставлен не полноценный интерфейс, либо был выбран неправильный фокус создания интерфейса, а может и самого класса.[/QUOTE]
фокус был очень правильный. в частности цель метода Krolik заключась в том что при обнаружении кролика, тигр или какая нить другая его разновидность начинали его преследование. что здеся с фокусом неправильно ? все очень даже правильно.
[QUOTE=Green]
В твоем примере базовый класс Tiger определяет какую сущность? Если движущийся объект, то надо было сосредоточиться на движении: stepLeft(), stepRight() и т.п. При этом наследник уже не задумывается о том как именно передвигается тигр, на лапах или на крыльях. [/QUOTE]
то есть ты предлагаешь свалить все в одну кучу ( класс ) : и ноги , и крылья и челюсти ? неправильно так как в этом случае у нас не будет получаться обычных тигров без крыльев - мне нужны оба типа - и с крыльями и без крыльев.
[QUOTE=Green]
сли же выбор способа передвижения определяется наследником, то и определять этот тип надо в наследнике. Либо базовый класс может иметь лишь ссылку на универсальный интерфейс движителя, а сам движитель задается в потомке или при конструировании объекта.[/QUOTE]
ну и какие это дает преимущества ? универсальный интерфейс для движущихся объектов ? и производный классы реализующие этот интерфейс ? так же та или иная стратегия перемещения зависит - от набора эффекторов - в одном случае это ноги , в другом случае это ноги и крылья. получается стратегии перемещения не взаимоменямы, и зависят о соответсующих классов - одна жестко от Tiger, другая от FlyTiger. таким образом данный подход теряет свою изначальную цель : универсальный интерфейс.
[QUOTE=Green]
В твоем примере базовый класс, агрегируя ноги, не предоставил интерфейс для управления ими.[/qUOTE]
конечно не предоствил. если бы интерфейс ног был выставлен наружу, то получается управлять движениями ног несчастного животного мог кто угодно. если же интерфейс ног скрыт от внешнего юзера - то тигр спокоен - его ноги принадежат только ему.
[QUOTE=Green]
Значит, изначально пользователь не должен был сосредотачиваться на типе движителя. Далее, например, ноги могли бы быть заменены в базовом классе на крылья, в крылья лучше не поджимать... :D
В твоем примере, если мы заменим ноги на крылья, нам придется менять имена в наследниках и даже реализацию наследников. Такая цепочка изменений - признак плохой архитектуры.[/QUOTE]
ищо раз , никто ноги тигру заменять на крілья не собирается, здеся речь идет о эволюции - в довесок к ногам появляются ищо и крылья - а ноги никто не отменял. это есть принцип полиморфизм. вся идея єтого примера состояла в том что продемонстрировать єволюцию системы, когда благодаря появлению нового органа, изменяется стратегия управления всеми агрегированными органами.
[QUOTE=Green]
Если же изначально предполагалось, что тигр двигается только на лапах, которые можно поджимать, должен был быть предоставлен интерфейс для такой операции. Он не был предоставлен, а значит интерфейс оказался не полноценным, а это признак плохой архитектуры. Но на начальном этапе это вполне нормально,- интерфейс обычно расширяется итерационно.[/quote]
нет речь идет всего лишь о двух типах тигров - с крыльями и без крыльев. но все тигры имеют ноги и челюсти. кому не предоставлен интерфейс ноги ? внешнему юзеру они не нужны - а то тигр обидится что его ногами всякие юзеры вместо него управляют.
[QUOTE=Green]
Если твой пример спроецировать на лошадь (базовый класс) со всадником (наследник), то получается, что наездник должен сам дергать за сухожилия ноги лошади, а не управлять движением через интерфейс "стремя". :D[/QUOTE]
испорльзвать в данном случае отношения наследования некорректно, здесь куда более очевидно отношение использования ( композиции из всадника и лошади). утверждать что лошадь с с всадником есть разновидность лошади смешно. так как ее внутреннее строение не изменятся, а просто присоединяесть ( к лошади как целое ) еще один объект-юзер - всадник.
[QUOTE=Green]
Одним словом, я с трудом могу представить (но все же могу, хотя это очень специфичные единичные случаи), где нужен protected.
В твоем примере он точно не нужен, а наоборот запутывает всю картину.[/QUOTE]
совершенно категорично заявляю что без использования protected здеся не обойтись. по крайней мере в рамках моей декомпозиции. можт приведешь свой пример ООП декомпозиции с тиграми ? тогда можно будет сравнивать.
[/QUOTE]
Смотрим в книгу, видим фигу...
Цитирую:
В хорошей архитектуре количество взаимосвязей должно сводиться к минимуму, чтобы не получалось запутанных клубков.
Ты сам то понимаешь, что обращаясь напрямую к реализации базового объекта, ты нарушаешь его концептуальную целостность и вводишь множество неявных взаимосвязей?
Видимо, не понимаешь.
[QUOTE=warchangel]
а вот те два - не надо доводить принцип инкапсуляции до идиотизма. инкапсуляция впервую очередь нужна для сокрытия деталей реализации от пользователя класса. то есть отношения использования класса. однако при отношении наследования от класса детали должны быть открыты, так как в данном случае мы являемся разработчиком класса а не его пользователем. другими словами инкапсуляция уместна при отношении использования, и не уместна при отношения наследования.
[/QUOTE]
А чем наследование отличается от использования?
Ничем. Одно есть частный вариант другого.
[QUOTE=warchangel]
гыг вот интересно ты что предлагаешь здеся посередине утомительного процесса разработки оторвать тигру ноги или челюсти ? че то нелогично. у всех тигров есть ноги и челюсти. и только у некоторых из них крылья. при этом они сохраняют свойства предка - имеют челюсти и ноги. именно поэтому они выделены в отдельный класс. таким образом показано что классы отличаются не только реализацией виртуальных методов но и таким свойством как полимофризм - то есть разное строение ( интерпритируется как различный набор переменных ). перевод слова полиморфизм получается практически дословный. однако так как теперь у данной разнвиднсти тигров есть крылья которые дают большое преимущество при преследовании, что дает нам право определить тигру новую стратегию преследования кролика, основанную на крыльях. достигаем этого посредством переопределения виртуального метода Krolik.
фокус был очень правильный. в частности цель метода Krolik заключась в том что при обнаружении кролика, тигр или какая нить другая его разновидность начинали его преследование. что здеся с фокусом неправильно ? все очень даже правильно.
то есть ты предлагаешь свалить все в одну кучу ( класс ) : и ноги , и крылья и челюсти ? неправильно так как в этом случае у нас не будет получаться обычных тигров без крыльев - мне нужны оба типа - и с крыльями и без крыльев.
ну и какие это дает преимущества ? универсальный интерфейс для движущихся объектов ? и производный классы реализующие этот интерфейс ? так же та или иная стратегия перемещения зависит - от набора эффекторов - в одном случае это ноги , в другом случае это ноги и крылья. получается стратегии перемещения не взаимоменямы, и зависят о соответсующих классов - одна жестко от Tiger, другая от FlyTiger. таким образом данный подход теряет свою изначальную цель : универсальный интерфейс.
конечно не предоствил. если бы интерфейс ног был выставлен наружу, то получается управлять движениями ног несчастного животного мог кто угодно. если же интерфейс ног скрыт от внешнего юзера - то тигр спокоен - его ноги принадежат только ему.
ищо раз , никто ноги тигру заменять на крілья не собирается, здеся речь идет о эволюции - в довесок к ногам появляются ищо и крылья - а ноги никто не отменял. это есть принцип полиморфизм. вся идея єтого примера состояла в том что продемонстрировать єволюцию системы, когда благодаря появлению нового органа, изменяется стратегия управления всеми агрегированными органами.
нет речь идет всего лишь о двух типах тигров - с крыльями и без крыльев. но все тигры имеют ноги и челюсти. кому не предоставлен интерфейс ноги ? внешнему юзеру они не нужны - а то тигр обидится что его ногами всякие юзеры вместо него управляют.
испорльзвать в данном случае отношения наследования некорректно, здесь куда более очевидно отношение использования ( композиции из всадника и лошади). утверждать что лошадь с с всадником есть разновидность лошади смешно. так как ее внутреннее строение не изменятся, а просто присоединяесть ( к лошади как целое ) еще один объект-юзер - всадник.
совершенно категорично заявляю что без использования protected здеся не обойтись. по крайней мере в рамках моей декомпозиции. можт приведешь свой пример ООП декомпозиции с тиграми ? тогда можно будет сравнивать.
[/QUOTE]
Для начала несколько замечаний.
1. "Мой тигр, что хочу то и делаю"? А я вот решил заменить твоему бызовому тигру ноги на гусеницы и столкнулся с проблемой переписывания всех классов-потомков.
2. Krolik - это часть тигра? :)
Совет - называй методы начиная с глагола, т.е. в данном случае логичнее назвать метод catchRabbit.
Давай ещё раз рассмотрим твой класс тигр. Это законченный класс с конечностями и стратегией поведения (управления этими конечностями). Что ты делаешь далее.. Далее ты навешиваешь на тигра крылья и вводишь через задний проход (по другому не назвать использование тобой protected) зонд для управления ногами и делаешь ему коррекцию поведения (методом трепонации видимо). Бедный тигр...
А теперь давай взгляним, что общего у этих тигров с точки зрения пользователя? Ничего, кроме единственного метода Krolik (catchRabbit). Т.е. у них лишь общий интерфейс относящийся к стратегии, но не к устройству тигра. Что касается реализации, то они тоже разные, за исключением агрегации ног и челюстей. Отсюда вывод, что можно было бы создать общий интерфейс ITiger, и наследовать от него двух совершенно разных тигров:
Код:
class ITiger
{
public:
Rabbit catchRabbit(int x, int y) = 0;
};
class Tiger :public ITiger
{
public:
Rabbit catchRabbit(int x, int y) {}
private:
Jaw _jaw;
Legs _legs;
};
class FlyTiger :public ITiger
{
public:
Rabbit catchRabbit(int x, int y) {}
private:
Jaw _jaw;
Legs _legs;
Wing _leftWing, _rightWing;
};
{
public:
Rabbit catchRabbit(int x, int y) = 0;
};
class Tiger :public ITiger
{
public:
Rabbit catchRabbit(int x, int y) {}
private:
Jaw _jaw;
Legs _legs;
};
class FlyTiger :public ITiger
{
public:
Rabbit catchRabbit(int x, int y) {}
private:
Jaw _jaw;
Legs _legs;
Wing _leftWing, _rightWing;
};
Ах да... это же твой тигр. Сейчас ты, наверное, начнешь утверждать, что у твоего тигра было множество других методов и полей, которые теперь придется копировать. Это только мне не позволено менять ему ноги на гусеницы, а ты то можешь добавить все что угодно.
Ок.
Ты сам определил, что у твоего тигра есть конечности и есть стратегия управления этими конечностями, при этом стратегия одного тигра отличается от стратегии другого, но у них есть общий набор конечностей. Выносим общее в один базовый класс, а различное выносим в конкретные дочерние классы. Т.о. мы получаем базовый класс TigerBase, который агрегирует общие органы и задает примитивные операции по их управлению: бежать, поджать ноги, клацнуть челюстью, т.е. то что едино для обоих тигров. Далее наследуем от этого класса классы обычного тигра с его поведением при погони за кроликом и летающего тигра с его поведением. По идее агрегатная база и стратегия погони - это разные сущности, но что бы избежать лишнего множественного наследования сведем ITiger и TigerBase в один класс:
Код:
class ITiger
{
public:
Rabbit catchRabbit(int x, int y) = 0;
};
class TigerBase :public ITiger
{
public:
void run() {}
void crossLegs() {}
void shutJaw() {}
private:
Jaw _jaw;
Legs _legs;
};
class Tiger :public TigerBase
{
public:
Rabbit catchRabbit(int x, int y) {}
};
class FlyTiger :public TigerBase
{
public:
Rabbit catchRabbit(int x, int y) {}
private:
Wing _leftWing, _rightWing;
};
{
public:
Rabbit catchRabbit(int x, int y) = 0;
};
class TigerBase :public ITiger
{
public:
void run() {}
void crossLegs() {}
void shutJaw() {}
private:
Jaw _jaw;
Legs _legs;
};
class Tiger :public TigerBase
{
public:
Rabbit catchRabbit(int x, int y) {}
};
class FlyTiger :public TigerBase
{
public:
Rabbit catchRabbit(int x, int y) {}
private:
Wing _leftWing, _rightWing;
};
Цитирую:
В хорошей архитектуре количество взаимосвязей должно сводиться к минимуму, чтобы не получалось запутанных клубков.[/QUOTE]
ну ка если можно поясни мне на моем примере как увеличелось кол-во взаимосвязей в связи с использованием protected? и как это вредит пользователю обоих классов ? и потом , не имея ничего против уменьшения кол-ва взаимосвязей, особенно ненужных, все таки приведу пример : человеческий ( да и не только ) мозг. нейронов там 15 милиардов , а связей между ними скоко ? причем как кто написал там проблематично даже выделить основные направления этих связей. и ничо отлично фунциклирует. и решает задачи гораздо посложнее. :D
[QUOTE=Green]
Ты сам то понимаешь, что обращаясь напрямую к реализации базового объекта, ты нарушаешь его концептуальную целостность и вводишь множество неявных взаимосвязей?
Видимо, не понимаешь.[/QUOTE]
да нет это ты не понимаешь сути поставленной мной задачи ( эволюционное моделирование ) которое весьма практически опровергает твое утверждение. все хорошо на своем месте , и инкапсуляция ( при использовании ), и доступ к защищенным членам , при наследовании.
[QUOTE=Green]
А чем наследование отличается от использования?
Ничем. Одно есть частный вариант другого.[/QUOTE]
ну раз они ничем не отличаются зачем тогда два отношения ? использование == наследование ? обошлись бы одним.
[QUOTE=Green]
Для начала несколько замечаний.
1. "Мой тигр, что хочу то и делаю"? А я вот решил заменить твоему бызовому тигру ноги на гусеницы и столкнулся с проблемой переписывания всех классов-потомков.[/QUOTE]
дык... с такой же долей вероятности может измениться и название или сигнатура какого нить открытого метода. тогда все равно придется переписывать все производные классы. так что использование private проблему не решает. если понадобилось изменение базового класса, значит либо базовый класс не был создан в соответсвии с исходной задачей, либо изменилась сама задача, но тогда эта уже не та задача под которую создавася исходный базовый класс. я же решал исходную задачу. данное тобой изложение вещей всего лишь подверждает твой принцип : хороший интерфейс - реализация через задницу.
если ж все таки очень нужен еще и тигр на гусеницах то :
Код:
class TigrNaGusenicax // не имеет в качестве базового Tiger или FlyTiger.
{
public:
Krolik( int x, int y )
{
// алгоритм преследования кролика, используя гусеницы.
}
protected:
Gusenicy _Gusenicy;
Chelusti _Chelusti;
// можт ему ищо и зенитную пушку 88 mm ?
}
{
public:
Krolik( int x, int y )
{
// алгоритм преследования кролика, используя гусеницы.
}
protected:
Gusenicy _Gusenicy;
Chelusti _Chelusti;
// можт ему ищо и зенитную пушку 88 mm ?
}
[QUOTE=Green]
2. Krolik - это часть тигра? :)
Совет - называй методы начиная с глагола, т.е. в данном случае логичнее назвать метод catchRabbit.
[/QUOTE]
[QUOTE=Green]
Давай ещё раз рассмотрим твой класс тигр. Это законченный класс с конечностями и стратегией поведения (управления этими конечностями). Что ты делаешь далее.. Далее ты навешиваешь на тигра крылья и вводишь через задний проход (по другому не назвать использование тобой protected) зонд для управления ногами и делаешь ему коррекцию поведения (методом трепонации видимо). Бедный тигр...
А теперь давай взгляним, что общего у этих тигров с точки зрения пользователя? Ничего, кроме единственного метода Krolik (catchRabbit).
Т.е. у них лишь общий интерфейс относящийся к стратегии, но не к устройству тигра. Что касается реализации, то они тоже разные, за исключением агрегации ног и челюстей. Отсюда вывод, что можно было бы создать общий интерфейс ITiger, и наследовать от него двух совершенно разных тигров:
Код:
class ITiger
{
public:
Rabbit catchRabbit(int x, int y) = 0;
};
class Tiger :public ITiger
{
public:
Rabbit catchRabbit(int x, int y) {}
private:
Jaw _jaw;
Legs _legs;
};
class FlyTiger :public ITiger
{
public:
Rabbit catchRabbit(int x, int y) {}
private:
Jaw _jaw;
Legs _legs;
Wing _leftWing, _rightWing;
};
{
public:
Rabbit catchRabbit(int x, int y) = 0;
};
class Tiger :public ITiger
{
public:
Rabbit catchRabbit(int x, int y) {}
private:
Jaw _jaw;
Legs _legs;
};
class FlyTiger :public ITiger
{
public:
Rabbit catchRabbit(int x, int y) {}
private:
Jaw _jaw;
Legs _legs;
Wing _leftWing, _rightWing;
};
Ах да... это же твой тигр. Сейчас ты, наверное, начнешь утверждать, что у твоего тигра было множество других методов и полей, которые теперь придется копировать. Это только мне не позволено менять ему ноги на гусеницы, а ты то можешь добавить все что угодно.
Ок.
Ты сам определил, что у твоего тигра есть конечности и есть стратегия управления этими конечностями, при этом стратегия одного тигра отличается от стратегии другого, но у них есть общий набор конечностей. Выносим общее в один базовый класс, а различное выносим в конкретные дочерние классы. Т.о. мы получаем базовый класс TigerBase, который агрегирует общие органы и задает примитивные операции по их управлению: бежать, поджать ноги, клацнуть челюстью, т.е. то что едино для обоих тигров. Далее наследуем от этого класса классы обычного тигра с его поведением при погони за кроликом и летающего тигра с его поведением. По идее агрегатная база и стратегия погони - это разные сущности, но что бы избежать лишнего множественного наследования сведем ITiger и TigerBase в один класс:
Код:
class ITiger
{
public:
Rabbit catchRabbit(int x, int y) = 0;
};
class TigerBase :public ITiger
{
public:
void run() {}
void crossLegs() {}
void shutJaw() {}
private:
Jaw _jaw;
Legs _legs;
};
class Tiger :public TigerBase
{
public:
Rabbit catchRabbit(int x, int y) {}
};
class FlyTiger :public TigerBase
{
public:
Rabbit catchRabbit(int x, int y) {}
private:
Wing _leftWing, _rightWing;
};
{
public:
Rabbit catchRabbit(int x, int y) = 0;
};
class TigerBase :public ITiger
{
public:
void run() {}
void crossLegs() {}
void shutJaw() {}
private:
Jaw _jaw;
Legs _legs;
};
class Tiger :public TigerBase
{
public:
Rabbit catchRabbit(int x, int y) {}
};
class FlyTiger :public TigerBase
{
public:
Rabbit catchRabbit(int x, int y) {}
private:
Wing _leftWing, _rightWing;
};
рассмотрим твой последний пример, который как я понял ты предлагаешь в качестве наилучшего из приведенных в этой теме. на самом деле с точки зрения пользователя твоих классов Tiger и FlyTiger их public-интерфейс выглядит так :
Rabbit catchRabbit(int x, int y) {}
void run() {}
void crossLegs() {}
void shutJaw() {}
бедный тигр опять не является единственным хозяином своих ног, гусениц, челюстей и крыльев, одержимый наверно. так пользователь, который в идеале должен всего лишь сказать тигру координаты кролика, имеет весьма интересную возможность порулить ногами тигра напрямую или к сильному удивлению тигра пощелкать его челюстями вне зависмости от желания самого тигра. более того в данную иерархию весьма проблематично добавить тигра на гусеницах. в то время как в моем примере эта задача разрешилась.
и еще... вдруг у летающего тигра, случилась поломка с крыльями. тогда в рамках моего решения он можт воспользоваться стратегией своего предка - догнать кролика на ногах. в твоем же случае такой возможности у него нету.
[/QUOTE]
Я уже несколько постов подрят это делаю. Думаю, что далее объяснять бессмысленно. :)
[QUOTE=warchangel]
и потом , не имея ничего против уменьшения кол-ва взаимосвязей, особенно ненужных, все таки приведу пример : человеческий ( да и не только ) мозг. нейронов там 15 милиардов , а связей между ними скоко ? причем как кто написал там проблематично даже выделить основные направления этих связей. и ничо отлично фунциклирует. и решает задачи гораздо посложнее. :D
[/QUOTE]
А ты пробовал производить модификацию структуры человеческого мозга, рефакторинг, устранение багов?
Идиотический пример. Как и этот:
[QUOTE=warchangel]
и еще... вдруг у летающего тигра, случилась поломка с крыльями. тогда в рамках моего решения он можт воспользоваться стратегией своего предка - догнать кролика на ногах. в твоем же случае такой возможности у него нету.
[/QUOTE]
[QUOTE=warchangel]
да нет это ты не понимаешь сути поставленной мной задачи ( эволюционное моделирование ) которое весьма практически опровергает твое утверждение. все хорошо на своем месте , и инкапсуляция ( при использовании ), и доступ к защищенным членам , при наследовании.
[/QUOTE]
Ты слышал такие понятия, как рефакторинг, архитектура системы?
В твоем понимании эволюционное моделирование - это количество (наращивание) не переходящее в качество (упорядоченность).
Советую почитать про рефакторинг.
[QUOTE=warchangel]
ну раз они ничем не отличаются зачем тогда два отношения ? использование == наследование ? обошлись бы одним.
[/QUOTE]
А кто говорит о знаке равенства?
Ты понимаешь фразу "Одно есть частный вариант другого"?
Попробую объяснить на пальцах.
Ягоды == Яблоко ?
Зачем два отношения, обошлись бы одним.
Млекопитающие == Кит ?
Зачем два отношения, обошлись бы одним.
[QUOTE=warchangel]
дык... с такой же долей вероятности может измениться и название или сигнатура какого нить открытого метода. тогда все равно придется переписывать все производные классы. так что использование private проблему не решает.
[/QUOTE]
Я тебе как кит киту скажу: плохо ты слушал своего товарища и не понимаешь ты значения инкапсуляции. Изменение открытого члена == изменение интерфейса.
[QUOTE=warchangel]
если понадобилось изменение базового класса, значит либо базовый класс не был создан в соответсвии с исходной задачей, либо изменилась сама задача, но тогда эта уже не та задача под которую создавася исходный базовый класс. я же решал исходную задачу.
[/QUOTE]
Базовый класс обычно создается под решение нескольких задач и должен обеспечивать возможность решения этих нескольких задач.
Если он больше не в состоянии это делать, значит базовый класс должын быть реорганизован.
[QUOTE=warchangel]
данное тобой изложение вещей всего лишь подверждает твой принцип : хороший интерфейс - реализация через задницу.
[/QUOTE]
Ссылку, пожалуйста, на такое мое утверждение.
[QUOTE=warchangel]
если ж все таки очень нужен еще и тигр на гусеницах то :
Код:
class TigrNaGusenicax // не имеет в качестве базового Tiger или FlyTiger.
{
public:
Krolik( int x, int y )
{
// алгоритм преследования кролика, используя гусеницы.
}
protected:
Gusenicy _Gusenicy;
Chelusti _Chelusti;
// можт ему ищо и зенитную пушку 88 mm ?
}
{
public:
Krolik( int x, int y )
{
// алгоритм преследования кролика, используя гусеницы.
}
protected:
Gusenicy _Gusenicy;
Chelusti _Chelusti;
// можт ему ищо и зенитную пушку 88 mm ?
}
[/QUOTE]
Но теперь то этот тигр не имеет ничего общего с предыдущими двумя, а мы вроде бы как говорим о наследовании, о базовых классах, общих интерфейсах. Кстати, а где у твоего тигра пасть?
[QUOTE=warchangel]
рассмотрим твой последний пример, который как я понял ты предлагаешь в качестве наилучшего из приведенных в этой теме. на самом деле с точки зрения пользователя твоих классов Tiger и FlyTiger их public-интерфейс выглядит так :
Rabbit catchRabbit(int x, int y) {}
void run() {}
void crossLegs() {}
void shutJaw() {}
бедный тигр опять не является единственным хозяином своих ног, гусениц, челюстей и крыльев, одержимый наверно. так пользователь, который в идеале должен всего лишь сказать тигру координаты кролика, имеет весьма интересную возможность порулить ногами тигра напрямую или к сильному удивлению тигра пощелкать его челюстями вне зависмости от желания самого тигра.
[/QUOTE]
Чтож в моем примере это легко исправляется, если нет необходимости открывать интерфейс базового класса:
Код:
class ITiger
{
public:
Rabbit catchRabbit(int x, int y) = 0;
};
class TigerBase
{
public:
void run() {}
void crossLegs() {}
void shutJaw() {}
private:
Jaw _jaw;
Legs _legs;
};
class Tiger :public ITiger, private TigerBase
{
public:
Rabbit catchRabbit(int x, int y) {}
};
class FlyTiger :public ITiger, private TigerBase
{
public:
Rabbit catchRabbit(int x, int y) {}
private:
Wing _leftWing, _rightWing;
};
{
public:
Rabbit catchRabbit(int x, int y) = 0;
};
class TigerBase
{
public:
void run() {}
void crossLegs() {}
void shutJaw() {}
private:
Jaw _jaw;
Legs _legs;
};
class Tiger :public ITiger, private TigerBase
{
public:
Rabbit catchRabbit(int x, int y) {}
};
class FlyTiger :public ITiger, private TigerBase
{
public:
Rabbit catchRabbit(int x, int y) {}
private:
Wing _leftWing, _rightWing;
};
Впрочем можно так же просто агрегировать TigerBase.
[QUOTE=warchangel]
более того в данную иерархию весьма проблематично добавить тигра на гусеницах. в то время как в моем примере эта задача разрешилась.[/QUOTE]
[/QUOTE]
В твоем примере задача не решилась. Во всяком случае, я не видел решения (представленное тобой выше решение ошибочное, я уже указал почему).
В моем же случае все элементарно:
Код:
class TrackTiger :public ITiger, private TigerBase
{
public:
Rabbit catchRabbit(int x, int y) {}
private:
Track _leftTrack, _rightTrack;
};
{
public:
Rabbit catchRabbit(int x, int y) {}
private:
Track _leftTrack, _rightTrack;
};
Ноги остались рудементарно, но это отрицательные следствия наследственности.
Чтобы такого не было можно сделать либо наследование лишь от интерфейса: class TrackTiger :public ITiger и заново агрегировать пасть, либо разделить базовый класс на два: тигр с пастью, тигр с ногами, порожденный от тигра с пастью.
В твоем примере, как понимаю, тигр так и останется с ногами и зондом в ж..пе.
Ты пойми, что использование protected не только увеличивает количество неявных взаимосвязей, но и ставит под удар реализацию базового класса, т.к. внутренние значения могут изменяться из вне (относительно базового класса).
:)))) где ? ну ка приведи свою цитатку. нигде не вижу разумного объяснения что типа такого : было n связей стало n+m связей и это повредило пользователю класса так как теперь он не может сделать то то.
[QUOTE=Green]
А ты пробовал производить модификацию структуры человеческого мозга, рефакторинг, устранение багов?[/QUOTE]
вообщем это происходит в процессе жизнедеятельности и эволюции обладателя этого мозга.
[QUOTE=Green]
Идиотический пример. Как и этот:
[/QUOTE]
это ты о своем последнем примере ? да действительно , лично мне трудно придумать более идотическую декомпозицию чем твой пример. TigerBase - гыг. это типа база откуда тигры выходят для охоты на кроликов ? гыг. гыг. гыг. тигры в шоке. между ними ходит легенда о таинственном их предке TigerBase - и не Tiger и не Base.
[QUOTE=Green]
Ты слышал такие понятия, как рефакторинг, архитектура системы?
В твоем понимании эволюционное моделирование - это количество (наращивание) не переходящее в качество (упорядоченность).
Советую почитать про рефакторинг.[/QUOTE]
[QUOTE=Green]
А кто говорит о знаке равенства?
Ты понимаешь фразу "Одно есть частный вариант другого"?
Попробую объяснить на пальцах.
Ягоды == Яблоко ?
Зачем два отношения, обошлись бы одним.
Млекопитающие == Кит ?
Зачем два отношения, обошлись бы одним.
[/QUOTE]
гыг во твоя цитатка :
[QUOTE=Green]
А чем наследование отличается от использования?
Ничем. Одно есть частный вариант другого.[/QUOTE]
[QUOTE=Green]
Я тебе как кит киту скажу: плохо ты слушал своего товарища и не понимаешь ты значения инкапсуляции. Изменение открытого члена == изменение интерфейса.
Базовый класс обычно создается под решение нескольких задач и должен обеспечивать возможность решения этих нескольких задач.
Если он больше не в состоянии это делать, значит базовый класс должын быть реорганизован.
Ссылку, пожалуйста, на такое мое утверждение.
Но теперь то этот тигр не имеет ничего общего с предыдущими двумя, а мы вроде бы как говорим о наследовании, о базовых классах, общих интерфейсах. Кстати, а где у твоего тигра пасть?
Чтож в моем примере это легко исправляется, если нет необходимости открывать интерфейс базового класса:
Код:
class ITiger
{
public:
Rabbit catchRabbit(int x, int y) = 0;
};
class TigerBase
{
public:
void run() {}
void crossLegs() {}
void shutJaw() {}
private:
Jaw _jaw;
Legs _legs;
};
class Tiger :public ITiger, private TigerBase
{
public:
Rabbit catchRabbit(int x, int y) {}
};
class FlyTiger :public ITiger, private TigerBase
{
public:
Rabbit catchRabbit(int x, int y) {}
private:
Wing _leftWing, _rightWing;
};
{
public:
Rabbit catchRabbit(int x, int y) = 0;
};
class TigerBase
{
public:
void run() {}
void crossLegs() {}
void shutJaw() {}
private:
Jaw _jaw;
Legs _legs;
};
class Tiger :public ITiger, private TigerBase
{
public:
Rabbit catchRabbit(int x, int y) {}
};
class FlyTiger :public ITiger, private TigerBase
{
public:
Rabbit catchRabbit(int x, int y) {}
private:
Wing _leftWing, _rightWing;
};
Впрочем можно так же просто агрегировать TigerBase.
В твоем примере задача не решилась. Во всяком случае, я не видел решения (представленное тобой выше решение ошибочное, я уже указал почему).
В моем же случае все элементарно:
Код:
class TrackTiger :public ITiger, private TigerBase
{
public:
Rabbit catchRabbit(int x, int y) {}
private:
Track _leftTrack, _rightTrack;
};
{
public:
Rabbit catchRabbit(int x, int y) {}
private:
Track _leftTrack, _rightTrack;
};
Ноги остались рудементарно, но это отрицательные следствия наследственности.
Чтобы такого не было можно сделать либо наследование лишь от интерфейса: class TrackTiger :public ITiger и заново агрегировать пасть, либо разделить базовый класс на два: тигр с пастью, тигр с ногами, порожденный от тигра с пастью.
В твоем примере, как понимаю, тигр так и останется с ногами и зондом в ж..пе.
Ты пойми, что использование protected не только увеличивает количество неявных взаимосвязей, но и ставит под удар реализацию базового класса, т.к. внутренние значения могут изменяться из вне (относительно базового класса).[/QUOTE]
вообщем свой пример ты рефакторишь уже в третий раз. как кто сказал : рост есть признаком несовершенства. моя же структура справилась со всеми изменениями без свой перерабоки. кроме того моя структура намного проще и связей в ней намного меньше чем в твоей. если кто не согласен обратитесь к учебникам по арифметике или овладевайте исскуством счета на пальцах.
[/QUOTE]
Не вижу смысла повторяться.
[QUOTE=warchangel]вообщем это происходит в процессе жизнедеятельности и эволюции обладателя этого мозга.
[/QUOTE]
Ты всерьез считаешь многосвязную архитектуру мозга хорошим примером для программ ЦЭВМ? :D
А не пробовал реактивный самолет заставить махать крыльями?
[QUOTE=warchangel]
это ты о своем последнем примере ? да действительно , лично мне трудно придумать более идотическую декомпозицию чем твой пример. TigerBase - гыг. это типа база откуда тигры выходят для охоты на кроликов ? гыг. гыг. гыг. тигры в шоке. между ними ходит легенда о таинственном их предке TigerBase - и не Tiger и не Base.
[/QUOTE]
Программирование не битология. Ошибка начинающих - создавать программные объекты проецированием реальных. На самом деле программные классы имеют более широкий смысл нежели отражение реальных физических объектов.
[QUOTE=warchangel]
гыг во твоя цитатка :
[/QUOTE]
где в цитате говорится о равенстве?
[QUOTE=warchangel]
вообщем свой пример ты рефакторишь уже в третий раз. как кто сказал : рост есть признаком несовершенства.
[/QUOTE]
А вот тут ты ошибаешься (несещь охинею).
Моя система приспосабливается минимальными изменениями к изменившимся условиям. Это и есть принцип итерационной разработки, частью которого является и рефакторинг.
Я советую тебе почитать про итерационную разработку, про TDD и рефакторинг. Узнаешь для себя много нового и полезного.
[QUOTE=warchangel]
моя же структура справилась со всеми изменениями без свой перерабоки. кроме того моя структура намного проще
[/QUOTE]
Ничуть. Голословное заявление.
Она не проще: имеет неявные связи, сложна для рефакторинга и реализации классов взаимосвязаны.
Кроме того она ошибочна (см. предыдущий мой пост), ты не смог породить гусеничного тигра и интерфейсом обычного.
Попробуй доказать обратное.
[QUOTE=warchangel]
и связей в ней намного меньше чем в твоей. если кто не согласен обратитесь к учебникам по арифметике или овладевайте исскуством счета на пальцах.[/QUOTE]
В твоей схеме множество неявных взаимосвязей.
Я устал уже это повторять. :D
Так и скажи: "я не знаю, что такое неявные взаимосвязи и поэтому не могу их увидеть в своей схеме".
Ты когда нибудь создавал архитектуры более двух класов в наследовании?
В заключении, советую тебе ещё почитать что-нибудь про архитектуру и дизайн, про рефакторинг, да и просто про ООП.
Кстати, почитай ещё "Дизайн и эволюция С++", там как раз есть и про protected.
Не в обиду будет сказано, из нашего общения понятно, что у тебя пока еще нет большого опыта проектирования, так вместо того чтобы спорить (точнее даже, тупить), лучше бы поинтересовался для чего иногда следует использовать protected. Я бы с большой поделился бы опытом, чем доказывать тебе то, до чего ты и сам дойдешь, если не будешь руководствоваться кустарными методами и методом научного тыка.
Ты всерьез считаешь многосвязную архитектуру мозга хорошим примером для программ ЦЭВМ? :D
А не пробовал реактивный самолет заставить махать крыльями?
Программирование не битология. Ошибка начинающих - создавать программные объекты проецированием реальных. На самом деле программные классы имеют более широкий смысл нежели отражение реальных физических объектов.
где в цитате говорится о равенстве?
А вот тут ты ошибаешься (несещь охинею).
Моя система приспосабливается минимальными изменениями к изменившимся условиям. Это и есть принцип итерационной разработки, частью которого является и рефакторинг.
Я советую тебе почитать про итерационную разработку, про TDD и рефакторинг. Узнаешь для себя много нового и полезного.
Ничуть. Голословное заявление.
Она не проще: имеет неявные связи, сложна для рефакторинга и реализации классов взаимосвязаны.
Кроме того она ошибочна (см. предыдущий мой пост), ты не смог породить гусеничного тигра и интерфейсом обычного.
Попробуй доказать обратное.
В твоей схеме множество неявных взаимосвязей.
Я устал уже это повторять. :D
Так и скажи: "я не знаю, что такое неявные взаимосвязи и поэтому не могу их увидеть в своей схеме".
Ты когда нибудь создавал архитектуры более двух класов в наследовании?
В заключении, советую тебе ещё почитать что-нибудь про архитектуру и дизайн, про рефакторинг, да и просто про ООП.
Кстати, почитай ещё "Дизайн и эволюция С++", там как раз есть и про protected.
Не в обиду будет сказано, из нашего общения понятно, что у тебя пока еще нет большого опыта проектирования, так вместо того чтобы спорить (точнее даже, тупить), лучше бы поинтересовался для чего иногда следует использовать protected. Я бы с большой поделился бы опытом, чем доказывать тебе то, до чего ты и сам дойдешь, если не будешь руководствоваться кустарными методами и методом научного тыка.[/QUOTE]
вообщем все шо ты тут написал полный бред и не имеет к моим постам и обсуждаемой теме никакого отношения. так что я думаю пройдет совсем немного времени и ты будешь рассказывать этот бред более благодарному слушателю : своему психиатру. и пожалуй я думаю тебе перед тем как читать книжки по рефакторингу следует все таки еще раз повторить основы арифметики. и если мы сравним мой опыт проектирования с твоим то ты где то прошел 0.0000000000000001% того пути который прошел я. так что товарсич, оглянитесь назад и начните сналача : с изучения арифметики. и уже , научившись правильно считать, беритесь за более сложные науки типа ООП проектирования. так что расти вам еще до меня и расти.
Как ты сам думаешь, твой последний пост показал тебя с профессиональной стороны?
Ты в очередной раз ничего не понял, т.к. зациклился на превосходстве своих тигров (так и не объяснив, чем же они лучше), но нахамить успел. Это уж точно по теме. :)
Возможно, опыт у тебя большой, в чем я очень сомневаюсь.
Впрочем, обезьяны уже порядка полумиллиона лет сбивают бананы палкой. Шикарный опыт, но даже до бумеранга они за эти годы не доросли.
Обычно, переходят на личности когда больше нечего сказать.
Тема исчерпана, закрываю обсуждение.
Что ж, удачи в тотальном использовании protected!
А удача тебе понадобиться.
P.S. Еще один "гений" создающий не первый год свой экстра супер файловый менеджер? :D