2011-01-20 2 views
0

Это вариант на моем previous question on how to hide inherited constructors. Как скрыть наследуемые методы:Delphi: Как скрыть методы предков?

Моделирование после того, что Delphi позволяет построить COM-объекты:

CoDOMDocument = class 
    class function Create: IXMLDOMDocument2; 
end; 

я есть завод, который создает объект, который реализует интерфейс:

CoCondition = class 
public 
    class function Create: ICondition; 
end; 

Этот работает отлично и отлично. Он отлично работает, хотя есть метод у предка, который называется Create. Это работает, потому что у меня нет ключевого слова overload. Как только я добавить overload ключевое слово: Delphi позволит унаследовали Create метод «просвечивать»:

CoCondition = class 
public 
    class function Create: ICondition; overload; 
end; 

Так что теперь CoCondition имеет два Create доступный метод:

class function CoCondition.Create: ICondition; 
constructor TObject.Create; 

И это неоднозначное, по которому который вы хотите вызвать. Исправить, очевидно, просто не должно быть ключевое слово overload (Зачем вам, вы ничего не перегружаете?). Ну получается, я я перегружать что-то:

CoCondition = class 
public 
    class function Create: ICondition; overload; 
    class function Create(const ConditionType: TConditionType): ICondition; overload; 
    class function Create(const PropertyName: string; const Operation: TConditionOperation; const Value: Variant): ICondition; overload; 
    class function Create(const ConditionType: TConditionType; const SubConditions: IInterfaceList): ICondition; overload; 
end; 

Поскольку я имею overload ключевое слово, класс имеет пять перегрузок, а не только четыре я хочу:

class function CoCondition.Create: ICondition; 
class function CoCondition.Create(const ConditionType: TConditionType): ICondition; overload; 
class function CoCondition.Create(const PropertyName: string; const Operation: TConditionOperation; const Value: Variant): ICondition; overload; 
class function CoCondition.Create(const ConditionType: TConditionType; const SubConditions: IInterfaceList): ICondition; overload; 
constructor TObject.Create; 

я только хочу, чтобы мои четыре перегрузки присутствовали, и другие. т. е. я хочу скрыть любые методы предков.

Как скрыть методы предков?


я также попытался явно объявить метод предка, но с его защитой, поэтому никто не может получить на него:

CoCondition = class 
protected 
    constructor Create; overload; 
public 
    class function Create(): ICondition; overload; 
    class function Create(const ConditionType: TConditionType): ICondition; overload; 
    class function Create(const PropertyName: string; const Operation: TConditionOperation; const Value: Variant): ICondition; overload; //leaf 
    class function Create(const ConditionType: TConditionType; const SubConditions: IInterfaceList): ICondition; overload; //AND/OR/NOT children 
end; 

Но это не компилируется из-за ambigious перегрузки unparametered Create().


я также рассмотрел:

CoCondition = class 
public 
    class function Make(): ICondition; overload; 
    class function Make(const ConditionType: TConditionType): ICondition; overload; 
    class function Make(const PropertyName: string; const Operation: TConditionOperation; const Value: Variant): ICondition; overload; //leaf 
    class function Make(const ConditionType: TConditionType; const SubConditions: IInterfaceList): ICondition; overload; //AND/OR/NOT children 
end; 

Но отверг его.


я мог просто выставить объект, который реализует объект:

TCondition = class(TInterfacedObject, ICondition) 
... 
public 
    constructor Create; overload; 
    constructor Create(const ConditionType: TConditionType); overload; 
    constructor Create(const PropertyName: string; const Operation: TConditionOperation; const Value: Variant); overload; //leaf 
    constructor Create(const ConditionType: TConditionType; const SubConditions: IInterfaceList); overload; //AND/OR/NOT children 
end; 

Но я думал, что все крутые парни скрывают свои объекты.

+0

Ну, вы просто не должны использовать Создать потому, что используется для конструкторов, и это не конструктор. –

+2

>> Но я думал, что все классные дети скрывают свои объекты. << Нет, не в этом примере, по крайней мере. Все дети, которые считают, что это заставит их здорово попробовать, - но они не могут. Как только они узнают об этом, они WOSH! стать прохладным дети. – TheBlastOne

+0

@ Давид Хеффернан Но Borland сделал это :( –

ответ

6

Скрытие методов невозможно, поскольку оно идет вразрез с основами объектно-ориентированного программирования.

Даже если язык будет поддерживать скрытие, вы всегда сможете обойти его.

Если, например, если вы создаете TAnimal класс с Name собственности, а затем создать TNamelessAnimal класс, где вы хотите, чтобы скрыть Name свойство.
Теперь вы можете добавить экземпляр TNamelessAnimal в ссылку TAnimal и получить доступ к объекту Name.
Это совершенно логично, так как TNamelessAnimal является TAnimal и поэтому имеет свойство Name.

--jeroen

+0

Ну, вы * можете * скрывать методы предков; просто не когда вы используете 'overload'. Но ответ ** не может быть сделан **, вероятно, так же корректен, как и будет. –

+0

Поскольку это методы класса, этот аргумент не применяется. Нет экземпляров до тех пор, пока функция класса не будет запущена. –

+1

Он делает; просто бросьте ссылку на класс в ссылку предка, и все готово. Например, когда 'Name' является свойством класса, тогда' TAnimalClass = класс TAnimal; AnimalClass: TAnimalClass; AnimalClass: = TNamelessAnimal; Writeln (AnimalClass.Name); 'будет обращаться к свойству класса. То же самое для методов класса. –

4

Скрытие метода не поддерживается в Delphi просто потому, что это не логично. Предположим, что у предка TAncestor есть открытый метод AMethod.Теперь объявите TDescendant = class (TAncestor) и переопределите AMethod как защищенный. Теперь пользователь может просто передать ваш TDescendant в TAncestor и получить доступ к методу, который должен был быть скрыт. Я не знаю, поддерживает ли какой-либо объектно-ориентированный язык методы скрытия у предков, но я сомневаюсь, что они есть.

+0

" может просто случай «должно быть« может просто _cast_ », я думаю? –

+0

@ Larry спасибо, исправлено. –

+0

Поскольку это методы класса, этот аргумент не применяется. после выполнения функции класса. –

0

Марк ваш новый «вариант» названный метод с директивой «вновь ввести»:

CoCondition = class 
public 
    class function Create: ICondition; reintroduce; 
end; 

Это позволяет «повторно ввести» имя метода с разными параметрами.

Но обратите внимание, что повторное введение - это не то же самое, что перегрузка (виртуальный метод) ... если вы вызываете эти методы с использованием ссылки на класс, метод Create, который вы вызываете, будет зависеть от конкретного типа ссылки на класс, вместо того, чтобы ссылаться на «самую производную версию».

Заметим также, что вы не может уменьшить заявленная видимость унаследованного метода ... если есть «общественность» Создать метод, унаследованный, затем реинтродукции «защищенный» Создать метод будет на самом деле не скрыть общественности по одному все.

2

Мой лучший способ методов «спрятать» предок объявить интерфейс с именами методов, которые важны для вас ... например:

IMyInterface = interface 
    procedure One; 
    procedure Two; 
end; 

Затем внедрить эти методы в своем классе, обнажая ваш класс в реализации IMyInterface, например:

TMyClass = class(TInterfacedObject, IMyInterface) 
PUBLIC 
    procedure One; 
    procedure Two; 
end; 

в другом месте в коде, огибает экземпляр вашего класса как IMyInterface (не TMyClass) вместо этого. Это аккуратно скрывает ВСЕ внутренние компоненты вашего класса и разбивает ваш код на хорошо разделенные модули.

Вы будете поражены тем, как объявление интерфейса может быть сделано, чтобы «смотреть» как класс, т.е. со свойствами тоже, например, это является законным и весьма полезным:

IMyInterface = interface 
    function GetSomething : integer; 
    procedure SetSomething(AValue : integer); 
    property Something : integer; read GetSomething write SetSomething; 
end; 

После того, как вы начнете использовать интерфейсы он будет трудно остановить.

1

Не беспокойтесь, чтобы сражаться за это. Просто поместите все свои методы и свойства реализации в защищенную область своего собственного подразделения, и это заставит вас использовать интерфейс.Другой выбор использовать другое имя для другого Создания методов с парами (ами) и снять перегрузку ключевого слову

Приветствие

Смежные вопросы