Вниз
Скачать: CL | DM;

ООП   Найти похожие ветки 

← →
МЯУ   (2004-09-10 22:59) [0]

У меня куча наследников одного класса, в котором описано большое количество абстрактных методов. Все методы в implementation описывать не охота (где-то 2/3 из них будут состоять из begin...end). Можно ли как нибудь перед вызовом метода проверить, overriden ли он у потомка?


← →
Defunct ©   (2004-09-10 23:14) [1]

Можно после вызова: ;)

Try
 Obj.DoSomething;
Except
 ShowMessage("Не перекрыт")
End;

PS: зачем создавать так много (2/3) ненужных методов?


← →
МЯУ   (2004-09-12 12:52) [2]

Defunct ©   (10.09.04 23:14) [1]
спасибо, всё замечятельно теперь работает.

а с методами вот какая ситуация:
у меня игра в directx, элементы управленяя создаются как потомки класса ТэЕлемент, у которово определены абстрактные методы mousemove, click, dragdrop и т.п. Так что, например, у кнопки всего три реально используемых метода (маусдаун/ап и клик), а все остальные воще не нужны.
Мож, кто подскажет, как сделать лучше?


← →
icWasya ©   (2004-09-13 12:42) [3]

Ctrl+Shift+C
и все пустые методы создадуться сами


← →
Ega23 ©   (2004-09-13 13:15) [4]

Обзови как virtual и abstract и вообще не описывай. Описание нужно будет только у потомков.


← →
Rem   (2004-09-13 13:36) [5]

Налицо нарушение наследования.
Создать базовый класс, в котором определено минимальное количество абстрактных методов. От него породить нужные классы.
Кроме этого, от него же определить нового абстрактного потомка, в котором добавлены новые абстрактные методы. И т. д.

TMyObjects --- TMyVehicle --- TMyBicycle
         |                   TMyMotorcycle
         |                   TMyCar --- TMyMercedes
         |                        | --- TMyMazda
         |
         | --- TMyFurniture --- TMySofa
         |                | --- TMyTable
         |
         | --- TMyOffices --- TMyComputer
                        | --- TMyFax


← →
TUser ©   (2004-09-13 14:03) [6]


> а с методами вот какая ситуация:
> у меня игра в directx, элементы управленяя создаются как
> потомки класса ТэЕлемент, у которово определены абстрактные
> методы mousemove, click, dragdrop и т.п. Так что, например,
> у кнопки всего три реально используемых метода (маусдаун/ап
> и клик), а все остальные воще не нужны.
> Мож, кто подскажет, как сделать лучше?

Надо создавать не один наследник для всего на свете, а иерархию классов, где на разных уровнях и в разных классах вводить ссотв. методы. Тогда не будет ничего лишнего.


← →
Ega23 ©   (2004-09-13 14:17) [7]

Rem   (13.09.04 13:36) [5]

В TMyMercedes мне больше всего My нравится...  :о)


← →
МЯУ   (2004-09-13 15:24) [8]

icWasya ©   (13.09.04 12:42) [3]
чего-то не создаются :(
а где нажимать-то?

Rem   (13.09.04 13:36) [5]
это конечно круто, но тогда при оперировании всеми этими объектами придётся проверять принадлежность к тому или иному классу, что немного накладно. Скажем, пользователь выполнил действия, вызывающие метод "залить полный бак", нужно смотреть, машина ли щяс под курсором или какая-нибудь MySofa... Так что мне больше нравится вариант от Defunct с try/except.. Мож это и не по ООПэвски, но мороки меньше :)


← →
Ega23 ©   (2004-09-13 15:29) [9]

if (CurrentObject is TMyCar) then
TMyCar(CurrentObject).Залить_Полный_Бак;


← →
Семен Сорокин ©   (2004-09-13 15:32) [10]

чего-то не создаются :(
Аськины шотакты отруби :)
а где нажимать-то?
в объявлении класса, можно через контекстное меню


← →
Rem   (2004-09-13 15:36) [11]

[8]
 Вот-вот... Указал пользователь объект, говорит: залить бак. Программа заливает, никаких проблем! Оказывается - диван! Куда лили, что лили, и во что это все вылилось? Программист доволен - никаких проверок делать не надо. Пользователь доволен - хохоту сколько - не программа, а анекдот!

И чего накладного в строке if (Object is TMyMercedes) then? Ни на йоту не накладнее try-except-end...

А так - какой-то Бейсик получается.

Если уж хочется простоты - используйте интерфейсы. Запросили интерфейс. Если получили - объект в состоянии выполнять определенные в интерфейсе действия. Не получили - значит этот объект этого делать всего этого не может... Но и тут не все так просто...


← →
суслик ©   (2004-09-13 15:37) [12]

лучше сделать все методы просто virtual с пустими телами, а не virtual abstract.

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


← →
Ega23 ©   (2004-09-13 15:41) [13]

лучше сделать все методы просто virtual с пустими телами, а не virtual abstract.

А чем лучше?


← →
Суслик ©   (2004-09-13 15:48) [14]


>  [13] Ega23 ©   (13.09.04 15:41)

в смысле это лучше чем try except.

лучше по скорости, сравни

type
  tcl = class
     procedure aa; virtual; abstract;
  end;

  tcl1 = class
     procedure aa; virtual;
  end;

procedure tcl1.aa;
begin
end;

procedure TForm1.Button4Click(Sender: TObject);
var
  c: tcl;
  c1: tcl1;
  kI: integer;
  kc, kca, kf: TLargeInteger;
begin
  queryperformancefrequency(kf);

  c := tcl.create();
  queryperformancecounter(kc);
  for kI := 1 to 10000 do
  begin
     try
        c.aa;
     except
     end;
  end;
  queryperformancecounter(kca);
  showmessage(format("%.8f", [(kca - kc) / kf]));

  c1 := tcl1.create();
  queryperformancecounter(kc);
  for kI := 1 to 10000 do
  begin
     c1.aa;
  end;
  queryperformancecounter(kca);
  showmessage(format("%.8f", [(kca - kc) / kf]));
end;


← →
Rem   (2004-09-13 15:50) [15]

[12] Что такое грабли и как ими пользоваться.

Конструкция try-except-finally-end придумана не для выпрямления кривых рук программиста, а обработки исключительных ситуаций, которые происходят не по вине программиста.

Вызывать абстрактный метод и защищать вызов конструкцией try-except-end - проявление высшего дилетантства.

Если хотите кучу граблей - определите Application.OnException. И будет вам "счасте"...


← →
МЯУ   (2004-09-13 15:53) [16]

суслик ©   (13.09.04 15:37) [12]

вызов try/except будет работать быстрее, чем 10 проверок типа "if (TMyObject is TMySofa) then"? блин, никогда бы не подумал. Ну да ладно, наверно всё же придётся переделать :)
или пустотелые методы сделать лучше?

а в принципе скорость не так уж и важна, я делаю пошаговую стратегию, там вообще все стоят на месте большую часть времени.


← →
Суслик ©   (2004-09-13 15:53) [17]


> [15] Rem   (13.09.04 15:50)

ты это мне?
Если да, то с какой стати?
Если нет, то почему [12] упомянул


← →
Суслик ©   (2004-09-13 15:54) [18]


>  [16] МЯУ   (13.09.04 15:53)


> или пустотелые методы сделать лучше?

я уже сказал, что в данном случае с учетом текущей реализации это лучше - меньше переделывать.
Сравни мой тест - разница в несколько порядков :)))


← →
Rem   (2004-09-13 15:56) [19]

LMD


← →
Ega23 ©   (2004-09-13 15:56) [20]

Суслик ©   (13.09.04 15:48) [14]

Ну может быть. Но речь-то о потомках и переопределённых методах, насколько я понял...

Я к тому, что я всегда такие методы через virtual; abstract; определял. Вот мне и интересно, чем просто virtual с пустым кодом может лучше быть...


← →
Суслик ©   (2004-09-13 15:58) [21]


> [20] Ega23 ©   (13.09.04 15:56)
> Суслик ©   (13.09.04 15:48) [14]

Чем, чем?
Тест запусти - разница в несколько порядков (в пять!). Вот и ответ.


> [19] Rem   (13.09.04 15:56)
> LMD

еще один борец за чистоту :))


← →
Ega23 ©   (2004-09-13 16:02) [22]

Суслик ©   (13.09.04 15:58) [21]

Блин, хорошо, перефразирую: "ПОЧЕМУ?"


← →
Суслик ©   (2004-09-13 16:07) [23]


> [22] Ega23 ©   (13.09.04 16:02)

Я что-то запутался.
Ты спрашиваешь почему в конкретном примере лучше не пользоваться try excet.

Как я понимаю, все дело в том, что try except имеет серьезные накладные расходы. Опять же насколько я понимаю structured exception handling реализован не в дельфи, а в ОС. В общем читай Рихтера, часть 5. Там было что-то про ресурсоемкость обработки исключений. Детали не помню


← →
Ega23 ©   (2004-09-13 16:09) [24]

Суслик ©   (13.09.04 16:07) [23]

Нет, я спрашиваю почему virtual с пустым телом метода работает быстрее, чем vitual; abstract; без тела метода.

С try - except и так всё ясно.


← →
Суслик ©   (2004-09-13 16:11) [25]


>  [24] Ega23 ©   (13.09.04 16:09)

а...

я это вроде не утверждал.

так что не знаю почему...


← →
Rem   (2004-09-13 16:11) [26]

[17]
 И Вам в том числе.
 
>>с какой стати

>>куча наследников одного класса... в котором описано большое количество... методов

С точки зрения затрат памяти: Что такое VMT Вам объяснять не нужно? Сколько памяти будут занимать "большое количество методов" в "куче наследников"?

С точки зрения семантики: Объект, который не может выполнить действие, не должен иметь метода, который предполагает это действие. Исключение - пустой метод в переопределенном классе, когда необходимо отменить какое-то действие. Иначе нет смысла этот метод определять. Директива abstract не спроста введена в Object Pascal.

С точки зрения Delphi: Сколько Warning"ов и Hint"ов выдаст компилятор? Или Warning"и и Hint"ы придумали в Borland"е от нечего делать? Или вы привыкли не обращать на них внимания?

С точки зрения ООП: Никто не отменял грамотное проектирование иерархии классов. Использование обсуждаемых здесь методов - грубое нарушение ООП.

Хотя, можно на это все не обращать никакого внимания. Пишите так, как пишите - и пусть пользователи (как вашей программы, так и классов) будут вам судьями.

Аминь!


← →
Ega23 ©   (2004-09-13 16:14) [27]

Блин, а как же тогда вот это понимать:
суслик ©   (13.09.04 15:37) [12]

лучше сделать все методы просто virtual с пустими телами, а не virtual abstract.

?

Я же именно про это в [13] спросил: "Чем лучше"?


← →
Суслик ©   (2004-09-13 16:17) [28]


> [26] Rem   (13.09.04 16:11)

Странный ты, е-мое.

Первая странность (вернее для данного форума норма, но для нормального человека все же нетипично) - отстутсвие внимания при чтении постов.

Вторая странность (опять же норма для форму, но не для жизни) - отсутсвие полезного совета в конкретной ситуации.

В данной ситуации решение с пустыми телами методов лучше чем тот ответ [1] с которым согласился автор вопроса. Вот и все. VMT и прочая безусловно полезная информация вполне могут быть и не использованы в данном случае. Несмотря на то, что мне самому подход автора не нравится все же рискнул дать конкретный совет (и даже сопроводил его доказывающим кодом) сделать не так, как хочет автор.


← →
суслик ©   (2004-09-13 16:20) [29]


> [27] Ega23 ©   (13.09.04 16:14)
> Блин, а как же тогда вот это понимать:

Ты выкинул вторую фразу

>>если я не ошибаюсь try except имеют накладные расходы, которые больше, чем просто вызов пустой функции.

а без нее изменяется смысл поста.

Я говорил, что в данной ситуации лучше сделать так, а не так как хочет автор, т.е. с try excep

Прошу прощения, если ввел в заблуждение.


← →
Rem   (2004-09-13 16:20) [30]

[21]
 А через полгода, имея на руках только откомпилированный модуль, Вы будете на себя же ругаться, когда, набрав название объекта, получите от Delphi длиннейший список методов, большинство из которых ничего не делает. И будете вспоминать, что же именно этот объект должен делать. И будете кричать ему "фас, аппорт, сидеть, лежать", а он будет молчать и мило улыбаться в ответ...


← →
Ega23 ©   (2004-09-13 16:21) [31]

суслик ©   (13.09.04 16:20) [29]

Да я уже понял, что ты про вторую фразу говорил.


← →
Суслик ©   (2004-09-13 16:23) [32]


> [26] Rem   (13.09.04 16:11)


> Использование обсуждаемых здесь методов - грубое нарушение
> ООП

Рискую перевести пост в потрепаться, но готов аргументированно поспорить.

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

Ты так уверен в своей правоте, как будто сам вопрос задавал :))


← →
Ega23 ©   (2004-09-13 16:26) [33]

Откуда ты знаешь, что автору точно не понадобится заправлять диван бензином. Очень может быть, что такая возможность в будущем предусмотрена, только для нее не написан пока функционал?

Гм, ну если данная игра что-то навроде ГЭГа, то вполне возможно...


← →
Суслик ©   (2004-09-13 16:28) [34]


>  [33] Ega23 ©   (13.09.04 16:26)

Все может быть.
Давать советы пусть и с виду страшно умные нельзя не зная специфики.


← →
Rem   (2004-09-13 16:32) [35]

[32]
Если надо заправлять диван бензином - его надо порождать от класса TFueledObject. Или использовать предка более низкого уровня.

Надо не подстраиваться под ошибки, а исправлять их.

Если проблемы возникают на столь раннем этапе - то потом их будет во много раз больше.

Мне надоела эта дискуссия...


← →
Суслик ©   (2004-09-13 16:38) [36]


> Мне надоела эта дискуссия...

а мне то как надоела :)))


← →
Rem   (2004-09-13 16:45) [37]

2 Суслик

 Ну тогда садитесь, переписывайте VCL, включая в TObject все методы и свойства TEdit, TLabel, TPanel, TComponent, TClientSocket... и еще сотен других объектов. Ведь программисты Borland"а изначально не знали бизнес-специфики Ваших задач. И вообще они зря за VCL взялись! Скорее всего (я подозреваю!) они много напортачили. Их логика - не Ваша (Вы ведь часто на Borland ругаетесь, признайтесь! ;)

Когда будет готово - выкладывайте в интернет Ваше универсальное хранилище. Вас признают!


← →
Суслик ©   (2004-09-13 16:53) [38]


>  [37] Rem   (13.09.04 16:45)

Тебе же надоело? :))

Если нет, то можно аргументированно пообсуждать.

Разберем твою фразу

> Ведь программисты Borland"а изначально не знали бизнес-специфики
> Ваших задач

Она лишена смысла в контексте того, что я сказал раньше про то, что неизвестна специфика задач.

Моя фраза была такой
>>Ты просто не можешь знать необходимый полиформизм.

Согласись, что ты действительно не можешь знать необходимый полиформизм. А не можешь, т.к. не знаешь задачу

Представь себе, что класс TElement, описывает все элементы системы. При этом суть игры такая, что любой элемент теоретически может выполнять любую роль. Вот! Пример! Например, в игре есть понятие "удар" (типа удар оружием).

В первой версии игры автор сделал как ты сказал - класс TWeapon с методом Strike. Все оружие он унаследовал от TWeapon. А вот представь, что во второй версии он хочет и табуретку наделить такаим свойством - чем плохо, за ножку и по голове. Но табуретка унаследована не от того класса, что делать. Ясно что - переделывать.

А вот представь, что все наследуется от TElement, у которого есть метод Strike. У многих классов он пуст. Переопределен только у оружия. Насколько проще реализовать возможность бить табуретом в этом случае?

Я не говорю, что надо делать так всегда. Твой пример с ВКЛ очень плох, просто ужасен - лужа все стерпит (с) (Игорь Шевченко)

Поэтому, давать советы делать глубокую иерархию можно только зная специфику задачи, вложенные в проект деньги, а как следствие перспективы проекта и пр. Ты этого знать не можешь - зачем утверждаешь, что делать все надо не так?


← →
Суслик ©   (2004-09-13 16:57) [39]


>  [38] Суслик ©   (13.09.04 16:53)

Добавка.

Перенос методов в предка и переопределение их только в некоторых потомках есть способ эмуляции множественного наследования - ты в независимости от текущей иерархии классов можешь наделить класс общими с другими классами свойсвами. В дельфи есть еще один способ такой эмуляции - интерфейсы. Не спорю, что в данном случае может он и лучше - знать бы задачу.



Страницы: 1 вся ветка

Скачать: CL | DM;



Память: 0.56 MB
Время: 0.021 c
14-1094810498
olookin
2004-09-10 14:01
2004.09.26
Есть ли термин?


14-1094155876
SergP
2004-09-03 00:11
2004.09.26
Подскажите прогу для "вытягивания" паролей сохраненных в ИЕ


6-1090215788
DimD
2004-07-19 09:43
2004.09.26
IdPOP3 и Proxy


14-1094447251
Layner
2004-09-06 09:07
2004.09.26
Японский отряд 731


6-1090174628
CrMhs
2004-07-18 22:17
2004.09.26
TClientSocket & TServerSocket ,please help!!!




   Наверх