Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.09.26;
Скачать: [xml.tar.bz2];

Вниз

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

 
МЯУ   (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 вся ветка

Форум: "Основная";
Текущий архив: 2004.09.26;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.56 MB
Время: 0.034 c
14-1094235781
Piter
2004-09-03 22:23
2004.09.26
Насчет списка погибших


3-1093509357
Nat
2004-08-26 12:35
2004.09.26
Пустая запись в DBGrid


3-1093618349
ceval
2004-08-27 18:52
2004.09.26
Нужно поле mr вывести в DBText


3-1093850711
ydv
2004-08-30 11:25
2004.09.26
глюки PReport


14-1094731238
Vlad Oshin
2004-09-09 16:00
2004.09.26
Сайт BlackMan a?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский