Форум: "Основная";
Текущий архив: 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.035 c