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

Скрыть 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 вся ветка

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



Память: 0.64 MB
Время: 0.025 c
14-1116784178
_silver
2005-05-22 21:49
2005.06.14
Тестирование СБИС.


8-1108553563
cuppykx
2005-02-16 14:32
2005.06.14
Пиксели цифровой камеры


14-1116861462
Ломброзо
2005-05-23 19:17
2005.06.14
ГОСТ 21552-84


14-1116928913
Stef
2005-05-24 14:01
2005.06.14
сжатие exe-файла


6-1111582563
hexen
2005-03-23 15:56
2005.06.14
Как получить HTML-код страницы




   Наверх