Форум: "Основная";
Текущий архив: 2005.06.14;
Скачать: [xml.tar.bz2];
ВнизСкрыть public-метод в наследнике. Найти похожие ветки
← →
Alexander Panov © (2005-05-30 20:10) [0]Как можно скрыть public-метод в наследнике класса?
К примеру, TStringList имеет 2 метода - Add и AddObject.
Как сделать невидимым для наследника метод Add?
← →
Гаврила © (2005-05-30 20:12) [1]В принципе никак не сделаешь.
Ибо всегда можно закастить под предка и вызвать метод
← →
Alexander Panov © (2005-05-30 20:14) [2]Гаврила © (30.05.05 20:12) [1]
А если без приведения типов?
Например:TGetList=class(TStringList)
private
function Add: Integer; reintroduce;
end;
В этом случае цель достигается, но получаем хинт, что метод нигде не используется.
← →
begin...end © (2005-05-30 20:16) [3]> Alexander Panov © (30.05.05 20:10)
Сужение области видимости невозможно. Если бы это было возможно, то и полиморфизма не было бы.
← →
Alexander Panov © (2005-05-30 20:17) [4]Ладно.
Спасибо всем.
Буду Exception выдавать в случае использования.
← →
Anatoly Podgoretsky © (2005-05-30 20:28) [5]Alexander Panov © (30.05.05 20:10)
И зачем? Психологичестки мешает? Если он виртуальный то сделай пустой в наследники, а также можно и скрыть через reintroduce
← →
Alexander Panov © (2005-05-30 20:33) [6]хм.
Я, наверное, немного ввел в заблуждение.
Хотел сказать - скрыть в наследнике от наследника.TGetList=class(TStringList)
private
function Add: Integer; reintroduce;
public
constructor Create;
end;
TGetChildList=class(TGetList)
end;
constructor TGetList.Create;
begin
Add;
end;
В принципе, если перенести метод в private-секцию, как заглушку и использовать при вызове, например, конструктора, то хинт выдаваться не будет.-)
И в наследнике не видно.
← →
Alexander Panov © (2005-05-30 20:35) [7]Anatoly Podgoretsky © (30.05.05 20:28) [5]
И зачем? Психологичестки мешает? Если он виртуальный то сделай пустой в наследники, а также можно и скрыть через reintroduce
А ведь пользователь класса ожидает, что метод работает по аналогии с родительским классом. Хотелось бы исключить любую ошибку.
← →
Anatoly Podgoretsky © (2005-05-30 20:37) [8]Alexander Panov © (30.05.05 20:35) [7]
Возбуди исключение, это самый нормальный метод. И документируй
← →
Alexander Panov © (2005-05-30 20:43) [9]Anatoly Podgoretsky © (30.05.05 20:37) [8]
Возбуди исключение, это самый нормальный метод. И документируй
А метод в [6] не подойдет?
← →
Чапаев © (2005-05-30 21:06) [10]Можно "предка" сделать приватным/защищённым полем "наследника" и делегировать нужные методы... Но это, конечно, не то, что хотел бы автор.
← →
Anatoly Podgoretsky © (2005-05-30 21:12) [11]Alexander Panov © (30.05.05 20:43) [9]
Я не понял его, особенно его вызов в Create.
Я никогда не пробовал сделать так, проверь сам пройдет или нет.
function Add: Integer; virtual; abstract; reintroduce;
Если получится то ты будешь иметь новую цепочку наследования и одновременно абстрактный метод, скрывающий метод предка.
← →
Alexander Panov © (2005-05-30 21:28) [12]Anatoly Podgoretsky © (30.05.05 21:12) [11]
такая цепочка не проходит, к сожалению.
← →
Anatoly Podgoretsky © (2005-05-30 21:32) [13]А жаль, я так надеялся. Ну тогда без abstract
← →
Defunct © (2005-05-30 21:41) [14]Извиняюсь за возможную грубость.
> В этом случае цель достигается, но получаем хинт
Ой ли, а не пофигу на тот хинт?
← →
BFG9k © (2005-05-30 21:43) [15]
> В принципе, если перенести метод в private-секцию, как заглушку
> и использовать при вызове, например, конструктора, то хинт
> выдаваться не будет
Дался тебе этот хинт. Хинты - обычное дело. Например при любом использовании PChar дельфи ругается - unsafe type. У нас своя голова за плечами :)
← →
Alexander Panov © (2005-05-30 21:44) [16]Defunct © (30.05.05 21:41) [14]
Ой ли, а не пофигу на тот хинт?
BFG9k © (30.05.05 21:43) [15]
Дался тебе этот хинт. Хинты - обычное дело. Например при любом использовании PChar дельфи ругается - unsafe type. У нас своя голова за плечами :)
У меня перед релизом не остается хинтов в программе.
← →
Defunct © (2005-05-30 21:46) [17]Alexander Panov © (30.05.05 21:44) [16]
Ясно, значит дело принципа ;>
и Pointer вы никогда не используете и PChar?
← →
Alexander Panov © (2005-05-30 21:49) [18]Defunct © (30.05.05 21:46) [17]
Использую, конечно.
← →
Defunct © (2005-05-30 22:09) [19]Alexander Panov © (30.05.05 21:49) [18]
А как же ж удается используя Pointer и PChar избегать всех hint"ов?
← →
Alexander Panov © (2005-05-30 22:21) [20]Defunct © (30.05.05 22:09) [19]
Приведи пример, в которм хинты выдаются?
← →
Defunct © (2005-05-30 22:40) [21]Alexander Panov © (30.05.05 22:21) [20]
const
Someconst : PChar = "А вот и хинт";
type
TSomerecord = Record
Addr : Pointer; // А вот и второй хинт
...
End;
Someproc = Procedure(Addr:Pointer); // третий хинт
Могу привести еще
← →
Alexander Panov © (2005-05-30 22:42) [22]Defunct © (30.05.05 22:40) [21]
Странно, у меня нет хинта ни в одном из 3-х примеров.
(D6)
← →
Гаврила © (2005-05-30 22:43) [23]Саш, хинт - не проблема, его можно погасить соответствующей директивой
{$HINTS OFF}
Я не совсем пойму - зачем это надо
2 Вопроса
1 кто будет пользоваться классом - потомком - ты или не ты?
2. метод статический или виртуальнй?
← →
Гаврила © (2005-05-30 22:46) [24]Если взять именно этот пример (Add, AddObject), то лучше наверно сделать так: переписать метод Add в секции паблик, но добавиьт параметр (сделать так же, как и в AddObject) (если например в стринг листе не должно оказаться итемов без обжектов)
← →
Defunct © (2005-05-30 22:46) [25]Alexander Panov © (30.05.05 22:42) [22]
Простите, Warning а не Hint в D7 звучит так:
1 - "Unsafe type PChar"
2 и 3 - "Unsafe type Pointer"
← →
Anatoly Podgoretsky © (2005-05-30 22:48) [26]Гаврила © (30.05.05 22:43) [23]
function Add(const S: string): Integer; override;
У предкаfunction Add(const S: string): Integer; virtual;
← →
Anatoly Podgoretsky © (2005-05-30 22:50) [27]Alexander Panov © (30.05.05 22:42) [22]
Появится в Д7, там это уже не безопасные типы, из-за .NET.
← →
Alexander Panov © (2005-05-30 22:51) [28]К сожаленю, я ошибся - спрятать метод все равно не удалось.
Это возможно только при условии вынесения предка в другой модуль, как я понял.
← →
Alexander Panov © (2005-05-30 22:53) [29]Ну что же, спасибо всем.
Похоже, что фокус не удастся.
---------
PS.
Гаврила © (30.05.05 22:43) [23]
1 кто будет пользоваться классом - потомком - ты или не ты?
Пользоваться буду я. Но ведь не надо зарекаться-)
← →
Anatoly Podgoretsky © (2005-05-30 22:56) [30]Ну спрятать невозможно по определению, можно начать новую цепочку наследования.
← →
Alexander Panov © (2005-05-30 22:59) [31]Anatoly Podgoretsky © (30.05.05 22:56) [30]
Да, увы мне-)
← →
Anatoly Podgoretsky © (2005-05-30 23:06) [32]Все таки так и осталось не понятным почему именно хочешь скрыть, ведь вполне достаточно изменить поведение, только надо учитывать и другие методы, например этот метод вызывает Insert который у предка как раз абстрактный, в отличии от Add, также еще есть и ряд других аналогичных методов.
Может надо подумать над перепроектированием? Что то хдесь не то, раз такое потребовалось.
← →
Alexander Panov © (2005-05-30 23:11) [33]Anatoly Podgoretsky © (30.05.05 23:06) [32]
Кратко опишу задачу:
Наследник от TStrinList используется для хранения списков объектов.
В наследнике объекты можно добавлять только методом AddObject(тоже переписанным).
← →
Alexander Panov © (2005-05-30 23:12) [34]Это делается для того, чтобы список формироваля строго по определенным правилам.
← →
Eraser © (2005-05-30 23:14) [35]Alexander Panov ©
А почему именно наследник от TStringList, а не TList например?
← →
Alexander Panov © (2005-05-30 23:17) [36]Eraser © (30.05.05 23:14) [35]
т
Мне необходимо наличие свойства Strings...
← →
Anatoly Podgoretsky © (2005-05-30 23:18) [37]Alexander Panov © (30.05.05 23:12) [34]
Почему бы не написать в наследнике методы, которые будут вызывать скажем исключение если они будут вызваны? Благо все они виртуальные или изменить их поведение, чтобы они следовали твоим требованиям. Ну не вижу острой необходимости скрывать.
← →
Alexander Panov © (2005-05-30 23:18) [38]Eraser © (30.05.05 23:14) [35]
По существу, в Strings хранятся ключи, по которым производится сортировка и поиск.
← →
Alexander Panov © (2005-05-30 23:19) [39]Anatoly Podgoretsky © (30.05.05 23:18) [37]
Анатолий, я уже понял, что не удастся скрыть-)
Поэтому последую твоему совету - перепишу метод с исключением.
← →
Anatoly Podgoretsky © (2005-05-30 23:22) [40]Alexander Panov © (30.05.05 23:19) [39]
Только просмотри все методы, чтобы не оказалось неожиданных обходных путей, например Delete ведь и удаление наверно должно следовать новому поведению. Все методы InsertXXX
← →
Alexander Panov © (2005-05-30 23:23) [41]Anatoly Podgoretsky © (30.05.05 23:22) [40]
Ну пока вот так класс-наследник определен.
от него будут наследоваться уже остальные.TMasterList=class(TStringList)
private
// FDB: IDBInterface; //Интерфейс для работы с БД
// FNet: INetInterface; //Интерфейс для работы с сетью
FG: TGuard; //Для работы с несколькими потоками
FSortDirect: Boolean;
FQuantity: Integer;
procedure Add; reintroduce;//Скрываем метод
procedure FreeObject(Index: Integer);
procedure CheckKey(aKey: String); //Проверка на пустой ключ
function GetKeys: TStringList;
function GetForumObject(Index: String): TForumObject;
procedure SetForumObject(Index: String; const Value: TForumObject);
procedure Enter;
procedure Leave;
// procedure CheckQuantity;
protected
function CompareStrings(const S1, S2: string): Integer; override; //Перекрыт для метода QuickSort
public
constructor Create; virtual;
destructor Destroy; override;
function AddObject(aForumObject: TForumObject): Integer; reintroduce;
procedure InsertObject(Index: Integer; aForumObject: TForumObject); reintroduce;
procedure Delete(Index: Integer); reintroduce; overload;
procedure Delete(aId: String); reintroduce; overload;
procedure Delete(aObject: TForumObject); reintroduce; overload;
function IndexOf(const S: string): Integer; override;
function Exists(aId: String): Boolean;
{
function DeleteFromDB(aId: String): Boolean; virtual;
function SyncToDB; virtual;
function SyncFromDB; virtual;
function SetObjectFromDB; virtual;
function AddObjectFromDB; virtual;
function WriteObjectToDB; virtual;
}
property Keys: TStringList read GetKeys;
property SortDirect: Boolean read FSortDirect write FSortDirect;
property ForumObject[Index: String]: TForumObject read GetForumObject write SetForumObject;
property Quantity: Integer read FQuantity write FQuantity;
end;
← →
Eraser © (2005-05-30 23:24) [42]Alexander Panov © (30.05.05 23:18) [38]
Ситуация понятна, сам так частенько делаю, в Strings храню UID на объект, но с написанием своего класса не заморачивался...
Как вариант можно использовать IndexOfObject, но о сортировки тут конечно речь не идёт.
Вообще конечно универсальный вариант - наследовать TStrings, а нужные методы переносить Copy/Paste.
← →
Alexander Panov © (2005-05-30 23:25) [43]Eraser © (30.05.05 23:24) [42]
С TStringList как раз удобно тем, что не надо методы вытаскивать в свой модуль;)
← →
Гаврила © (2005-05-30 23:33) [44]Я в таком случае сделал бы по варианту [10].
Тем более, если планируется дальнейшее наращивание наследников
← →
palva © (2005-05-30 23:33) [45]begin...end © (30.05.05 20:16) [3]
> Сужение области видимости невозможно. Если бы это было возможно, то и полиморфизма не было бы.
В языке C++ возможно при определении класса объявить тип наследования. Если он, к примеру, private то публичные методы наследуемого класса в наследующем становятся private.
← →
palva © (2005-05-30 23:51) [46]palva © (30.05.05 23:33) [45]
Поясню, хотя это, возможно, off topic
#include <iostream.h>
class a
{
public:
int i;
};
class b : a
{
public:
int j;
};
int main() {
b bb;
bb.j = 7;
bb.i = 8; // cannot access public member declared in class "a"
cout << "adfasdf";
return 0;
}
Если написать публичное наследование (в делфи оно всегда публичное)
class b : public a
то диагностика исчезнет
← →
jack128 © (2005-05-31 00:09) [47]palva © (30.05.05 23:51) [46]
Если я передам в функцию, которая принемает a, объект реально являющийся b , то такая диагностика не работает..
← →
palva © (2005-05-31 00:24) [48]jack128 © (31.05.05 00:09) [47]
Это - да. Меня просто смутило утверждение "Если бы это было возможно, то и полиморфизма не было бы" Честно говоря, смутно представляю себе, что такое полиморфизм, но в C++ это возможно.
← →
default © (2005-05-31 00:29) [49]palva © (31.05.05 00:24) [48]
jack128 имеет ввиду что это работает только на стадии компиляции
"сместить" VMT для удаления закрываемого в потомке метода нельзя(по-хорошему) ибо весь полиморфизм работающий на этих VMT поломается
← →
SergP © (2005-05-31 02:04) [50]
> TGetList=class(TStringList)
> private
> function Add: Integer; reintroduce;
> end;
А если не делать TGetList наследником TStringlist? А сделать типа так:
TGetList=class
...
private
SL:TStringList;
...
end;
← →
Alexander Panov © (2005-05-31 02:42) [51]SergP © (31.05.05 2:04) [50]
Тогда придется переписывать методы для доступа к SL.
← →
VMcL © (2005-05-31 07:32) [52]>>Alexander Panov © (31.05.05 02:42) [51]
Э-э-э.. так Вам шашечки или ехать? :-)
Если нужно по-честному именно скрыть, то делегирование, IMHO, один из лучших вариантов. Если не единственный.
>>SergP © (31.05.05 02:04) [50]
См. [10]. "Всё уже украдено до нас" (c)
← →
Alexander Panov © (2005-05-31 10:00) [53]VMcL © (31.05.05 7:32) [52]
Э-э-э.. так Вам шашечки или ехать? :-)
Если нужно по-честному именно скрыть, то делегирование, IMHO, один из лучших вариантов. Если не единственный.
Ну скрыть - это ведь побочная задача, и далеко не самая важная-)
Более приоритетная - удобство использования класса.
Поэтому - ну не удалось скрыть, ну и ладно-)
← →
Alexander Panov © (2005-05-31 10:00) [54]Еще раз спасибо всем за обсуждение.
← →
Игорь Шевченко © (2005-05-31 10:33) [55]Не надо использовать наследование. Надо использовать композицию.
Пост [50] наиболее подходящее решение.
Не надо путать программистов всякими reintroduce использующимися не по прямому назначению :)
← →
Alexander Panov © (2005-05-31 11:04) [56]Игорь Шевченко © (31.05.05 10:33) [55]
Не надо использовать наследование. Надо использовать композицию.
А чем лучше?
Впервые решил использовать наследование, а тут обломать хочешь намерение такое;)
← →
Игорь Шевченко © (2005-05-31 11:40) [57]Alexander Panov © (31.05.05 11:04) [56]
"Если родительский класс в большинстве случаев будет "подменять" своего потомка, то используется наследование. Если же родительский класс нужен лишь, чтобы класс-потомок мог использовать некоторые его свойства, то лучшим выбором будет композиция.
Одной фразой: чем больше класс-потомок похож на родительский класс, тем предпочтительнее использовать наследование, а не композицию."
← →
DiamondShark © (2005-05-31 12:06) [58]Наследование должно сдохнуть.
← →
Alexander Panov © (2005-05-31 12:09) [59]Игорь Шевченко © (31.05.05 11:40) [57]
А как, например, изменить порядок сортировки в TStringList без наследования?
Да и большинство свойств родительского кдасса используется по назначению.
← →
begin...end © (2005-05-31 12:12) [60]> Alexander Panov © (31.05.05 12:09) [59]
> А как, например, изменить порядок сортировки в TStringList
> без наследования?
StringList.CustomSort(...)
:-)
← →
Игорь Шевченко © (2005-05-31 12:14) [61]DiamondShark © (31.05.05 12:06) [58]
Вместе с полиморфизмом или отдельно ?
Alexander Panov © (31.05.05 12:09) [59]
> А как, например, изменить порядок сортировки в TStringList
> без наследования?
CustomSort вызывать ?
> Да и большинство свойств родительского кдасса используется
> по назначению.
А зачем тогда такой геморрой с скрытием метода Add ?
← →
Alexander Panov © (2005-05-31 12:16) [62]begin...end © (31.05.05 12:12) [60]
StringList.CustomSort(...)
Я же не буду после каждой операции со списком CustomSort вызывать?
Игорь Шевченко © (31.05.05 12:14) [61]
А зачем тогда такой геморрой с скрытием метода Add ?
Это, в общем-то, был единственный непонятный на тот момент вопрос.-)
← →
DiamondShark © (2005-05-31 12:26) [63]
> Игорь Шевченко © (31.05.05 12:14) [61]
Отдельно, конечно.
Для полиморфизма есть своя чёткая, однозначная концепция -- реализация интерфейсов.
Для реюза -- тоже. Композиция.
Наследование, как оно существует в распространённых языках, слишком мутно и перегружено: оно одновременно и описание интерфейса, и реализация интерфейса и реюз кода.
← →
Игорь Шевченко © (2005-05-31 12:48) [64]DiamondShark © (31.05.05 12:26) [63]
А вот народ пишет такое:
"Наследование является полезной концепцией программирования, но не всегда стоит прибегать к ней. Зачастую с подобными задачами лучше справляются интерфейсы. Данный раздел и раздел Случаи использования интерфейсов помогут выбрать нужный подход.
Наследование лучше использовать в следующих случаях.
1.Иерархия наследования представляет собой отношения тождественности (is-a), а не отношения включения (has-a).
2.Можно повторно использовать код из базовых классов.
3.Необходимо применить тот же класс и методы к другим типам данных.
4.Иерархия класса содержит довольно мало уровней, и другие разработчики вряд ли будут добавлять в нее другие уровни.
5.Необходимо внести коренные изменения в производные классы путем изменения базового класса. "
http://msdn.microsoft.com/library/rus/default.asp?url=/library/rus/vbcn7/html/vaconwhenuseinheritance.asp
← →
DiamondShark © (2005-05-31 13:03) [65]Из диалога с директором школы, получившим в подарок класс ДВК
- Посоветуйте, как нам получить от этого максимальную пользу.
- Этого я не могу. Но могу посоветовать, как получить от этого минимальный вред.
> Игорь Шевченко © (31.05.05 12:48) [64]
Это не то. Это из разряда "как с наименьшим гемороем пользоваться тем, что уже есть".
Посмотрите лучше сюда:
http://zonnon.ethz.ch/papers/Zonnon_Language_Report_v02r02_2_y041101.pdf
← →
Игорь Шевченко © (2005-05-31 14:33) [66]DiamondShark © (31.05.05 13:03) [65]
> Посмотрите лучше сюда:
Посмотрел. Но не могу сказать, насколько приживется.
← →
pasha_golub © (2005-05-31 19:11) [67]Эта, не убивайте ветку, плиз. У меня в свете этого обсуждения тоже вопрос. Просто сейчас некогда. ;0)
← →
Anatoly Podgoretsky © (2005-05-31 19:22) [68]pasha_golub © (31.05.05 19:11) [67]
Эта, никому не запрещено создавать ветки
← →
Суслик © (2005-05-31 19:26) [69]Я солидарен с [10] и [50]. Я бы сделал так. Если, конечно, Александру не нужно передавать свой список
куда-то, где ожидается интерфейс базового класса TStringList.
А вообще, все зависит от задачи, которая стоит перед Александром.
В некоторых случаях, я ничего плохого в совете Анатолия (возбуждать исключение) не вижу.
← →
Суслик © (2005-05-31 19:28) [70]Если не ошибаюсь, то в плюсах можно именно прятать методы/конструкторы/деструкторы.
← →
Anatoly Podgoretsky © (2005-05-31 19:28) [71]Это если надо сделать иммитацию абстрактного метода или просто предотвратить неверное использование. Но все определяется задаче, я же подробностей не знаю.
← →
Суслик © (2005-05-31 19:53) [72]Тут высказывалось отрицательное отношение к наследованию.
Не вижу ничего в нем плохого. ИМХО в дизайне должно быть все сбалансировано.
В качестве баланса могу привести в пример библиотеку "свинг" в java.
Полагаю, что реализованный у них подход по использованию полиформизма и наследования очень лаконичен.
← →
Cobalt © (2005-06-01 00:49) [73]2 Суслик © (31.05.05 19:53) [72]
Подробности можно?
* копаться в исходниках как-то лень...*
Страницы: 1 2 вся ветка
Форум: "Основная";
Текущий архив: 2005.06.14;
Скачать: [xml.tar.bz2];
Память: 0.65 MB
Время: 0.04 c