Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
14-1117027575
Задающий вопросы
2005-05-25 17:26
2005.06.14
Звчем нужна копка Scroll Lock?


4-1114250886
Керик
2005-04-23 14:08
2005.06.14
SHBrowseForFolder


3-1115290127
Black Fox
2005-05-05 14:48
2005.06.14
Ошибка доступа к метафайлу


14-1117172312
Sergey13
2005-05-27 09:38
2005.06.14
Про работу DMClient


14-1116833363
Иксик
2005-05-23 11:29
2005.06.14
Коллега прислал





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский