Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.116.24.105] |
|
Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Если я в родительском классе объявлю метод с некоторым именем и в дочернем классе объявлю метод с тем же именем (но с другими параметрами), то метод из родительского класса будет недоступен (не унаследуется):
type TX = class procedure Z; end; TY = class(TX) procedure Z(I: Integer); end; procedure TX.Z; begin end; procedure TY.Z(I: Integer); begin end; var Y: TY; begin Y := TY.Create; Y.Z // Not enough actual parameters. end. Но! Если дочерний метод будет перегружен (например, для того, чтобы сделать 2 варианта вызова), то и родительский унаследуется тоже! type TX = class procedure Z; end; TY = class(TX) procedure Z(I: Integer); overload; procedure Z(S: String); overload; end; procedure TX.Z; begin end; procedure TY.Z(I: Integer); begin end; procedure TY.Z(S: String); begin end; var Y: TY; begin Y := TY.Create; Y.Z // Well done! end. А я не хочу, чтобы родительский метод наследовался! Можно ли это сделать? Желательно, чтобы это работало, начиная с Delphi7... Добавлено И вообще, можно ли как-то обозначить в дочернем классе, какие методы нужно наследовать, а какие нет (если точнее, то меня даже больше волнует, какие из них будут public, а какие private/protected... в предыдущем вопросе имеется в виду то же самое). |
Сообщ.
#2
,
|
|
|
ну а что мешает изначально у родителя метод сделать приватным, а у дочернего публичные методы?
по умолчанию все идут publiched (если мне память не изменяет) |
Сообщ.
#3
,
|
|
|
Цитата ViktorXP @ Мешает то, что я не смогу использовать родительский метод.ну а что мешает изначально у родителя метод сделать приватным, а у дочернего публичные методы? Суть в том, что в методе родительского класса выполняется одна работа, а в дочернем - другая. Поэтому, если из дочернего класса будет вызван метод родителя, он сработает не в кассу. Но доступными должны быть и те методы, и другие, но только в своих классах. |
Сообщ.
#4
,
|
|
|
Цитата Jin X @ А я не хочу, чтобы родительский метод наследовался! наверное будет куда правильнее сделать два наследника. с разными реализациями. или переделать логику на интерфейсы. пс. просто без общей идеи зачем это сложно судить что конкретно ты хочешь получить. пс. то что метод виден это не бага. подобное поведение задокументировано Overloading_Methods пс.пс. по своей практике скажу что подобное поведение логично правильное. так как тебе чаще нужно добавить однодоменную функцию, а не заменить (если ты конечно не перегружаешь) |
Сообщ.
#5
,
|
|
|
Так, я и не говорю, что это баг
Просто есть полиморфизм, который как раз заключается в том, чтобы при одинаковых именах иметь разную реализацию у предка и наследника. Бывает же такое, что у наследника какая-то функция (метод) уже не нужна, для него это рудимент. Но как я понял, единственный вариант - это объявить метод таким же образом и реализовать его в теми параметрами, что у предка. Странно, что такого функционала нет. |
Сообщ.
#6
,
|
|
|
Посмотри, как сделано в VCL. Базовый класс называется TCustom*, и большую часть методов и полей имеет protected. А для юзания наследуется T*, который просто открывает нужные члены класса.
Добавлено Да, и простые protected/private видны внутри того же модуля, чтобы отключить эту видимость - надо добавить strict |
Сообщ.
#7
,
|
|
|
Цитата Fr0sT @ С property, допустим, понятно. А что делать с методами? Как их "открыть"?Посмотри, как сделано в VCL. Базовый класс называется TCustom*, и большую часть методов и полей имеет protected. А для юзания наследуется T*, который просто открывает нужные члены класса. Можно, конечно, сделать так: type TCustomBlaBla = class protected procedure DoSomething; end; TBlaBla = class(TCustomBlaBla) public procedure Something; end; procedure TBlaBla.Something; inline; begin DoSomething end; Тем более, если потом я захочу унаследовать что-то от TBlaBla, опять та же проблема возникнет... Цитата Fr0sT @ Мне нужна видимость не внутри, а снаружи как раз-таки... Да, и простые protected/private видны внутри того же модуля, чтобы отключить эту видимость - надо добавить strict |
Сообщ.
#8
,
|
|
|
Тьфу блин, совсем ты запутал своими тредами, уже и тут начал подвох искать.
TX = class strict private procedure Z; end; ... Y.Z; // [DCC Error] Unit1.pas(843): E2389 Protected member 'TX.Z' is inaccessible here |
Сообщ.
#9
,
|
|
|
type TX = class procedure Z; end; TY = class(TX) procedure Z(I: Integer); overload; procedure Z(S: String); overload; end; procedure TX.Z; begin end; procedure TY.Z(I: Integer); begin end; procedure TY.Z(S: String); begin end; var Y: TY; X: TX; begin Y := TY.Create; Y.Z; // допустим у тебя всё получилось и данная конструкция не работает // а если мы сделаем так? TX(Y).Z; // или так? X:=Y; X.Z; end. |
Сообщ.
#10
,
|
|
|
Shaggy, иии???
Таким образом можно запустить любой родительский метод, причём тут это? Мне это нужно не для того, чтобы злостный программист не смог запустить этот метод никакими ухищрениями и кулхацкерском, а чтобы просто убрать метод из области нормальной видимости. Чтобы при написании Y.Z выводилась ошибка, что мол "фуцк офф, нот инаф акшуал параметерс", чувак. Т.е. именно в потомке заменить Z на Z(I) и Z(S), убрав Z. А так-то понятно, что можно и ShowModal попытаться запустить для TList или узнать его ThreadID Цитата Fr0sT @ Какой подвох? Тьфу блин, совсем ты запутал своими тредами, уже и тут начал подвох искать. Мне надо сделать так, чтобы у предка TX был доступен метод (ИЗВНЕ!!!) Z, а у потомка TY - только Z(I) и Z(S), но не Z. А ты приводишь код, в котором даже TX.Z не будет доступен вообще. Зачем??? |
Сообщ.
#11
,
|
|
|
Цитата Jin X @ Таким образом можно запустить любой родительский метод, причём тут это? Мне это нужно не для того, чтобы злостный программист не смог запустить этот метод никакими ухищрениями и кулхацкерском, а чтобы просто убрать метод из области нормальной видимости. Чтобы при написании Y.Z выводилась ошибка, что мол "фуцк офф, нот инаф акшуал параметерс", чувак. Т.е. именно в потомке заменить Z на Z(I) и Z(S), убрав Z. А так-то понятно, что можно и ShowModal попытаться запустить для TList или узнать его ThreadID никаких хаков тут нет и твоё желание невыполнимо. убрать что-либо из интерфейса предка в потомке нельзя. overload разрешает существование одноимённых (всех) методов. можно скрыть метод предка объявив одноимённый метод в потомке. ооп тут нипричём, можно описать, например, IntToStr в своём модуле и скрыть объявление стандартной и если на уровне модулей всё разрешается с помощью qualified name и/или overload, то для объектов нужно приведение к предку кроме того, ты можешь забыть про своё "гениальное" архитектурное решение и написать примерно так: var Y: TY; ... procedure Something(X:TX); begin X.Z; end; ... Something(Y); |
Сообщ.
#12
,
|
|
|
Цитата Shaggy @ Здесь (в твоём примере) будет выполнен метод предка, а не потомка. Т.е. выполнен код X.Z (если он не виртуальный). Не надо путать.кроме того, ты можешь забыть про своё "гениальное" архитектурное решение и написать примерно так: Одноимённый метод предка можно скрыть объявлением метода с тем же именем... Если только он не overload(!) В этом-то и весь нюанс. Но я уже понял, что нужного мне механизма нет. Значит, нужно "идти другим путём". Что-то вроде описанного выше #7 |
Сообщ.
#13
,
|
|
|
Цитата Jin X @ Мне надо сделать так, чтобы у предка TX был доступен метод (ИЗВНЕ!!!) Z, а у потомка TY - только Z(I) и Z(S), но не Z. Вот сформулировал бы по-нормальному задачу с самого начала - и не было бы недопониманий. Твоей хотелке только интерфейсы помогут. Либо перекраивать структуру объектов, наследуя TX с методом Z и TY с методами Z(byte), Z(string) от общего TW, у которого Z нет вообще. |
Сообщ.
#14
,
|
|
|
Цитата Jin X @ Одноимённый метод предка можно скрыть объявлением метода с тем же именем... Если только он не overload(!) В этом-то и весь нюанс. Поэтому, если очень нужно, то можно использовать финт ушами - создать промежуточный класс TXY, в котором объявить один из методов, например Z(I:integer) без overload. А в TY добавить нужные overload-ы. Не удобно, конечно, но что поделаешь, раз "нужного механизма нет". |
Сообщ.
#15
,
|
|
|
leo, понятно. Да, вариант тоже не фонтан.
Я вот думал, что можно будет его спрятать в private, но... он не прячется, а создаётся ещё один метод с таким же именем (только private), но родительский метод всё равно виден (извне). Fr0sT, не знаю, как ещё нормальнее формулировать? |