2009-07-20 52 views
1

子类可以访问父类中的受保护函数,但父类不能访问子类中的受保护函数。如何访问子类中的函数?

我想保持两个类尽可能私有。父类是一种形式,只有一次使用实例。子类中的所有函数都是静态的,它从父类继承。

如何从父类访问子类中的非公共静态方法(在另一个单元中)?

编辑:

父类(第一部):

interface 

type 
TParent = class 
    public 
    procedure Initialize; 
    protected 
    procedure Test; virtual; 
end; 

implementation 

procedure TParent.Initialize; 
begin 
    Writeln('Initializing'); 
    Test; 
end; 

procedure TParent.Test; 
begin 

end; 

子类(第二单元):

interface 

uses 
ParentClass; 

type 
TChild = class(TParent) 
protected 
    procedure Test;override; 
end; 

implementation 

procedure TChild.Test; 
begin 
    Writeln('Test!'); 
end; 

代码(第三单元):

var c:TParent; 

begin 
    try 
    c := c.Create; 
    c.Initialize; 
    c.Free; 
    Readln; 
end; 

输出只是“初始化”。我试图调试它,它没有达到子类。

+0

它永远不会因为你是创建类错到达子类。将您的创建更改为读取C:= TChild.Create,它将起作用。 – skamradt 2009-07-20 19:02:01

+0

您正在实例化该类错误。我想你之前已经被告知过。编译器在你调用`c.Create`时没有警告你?如果你想创建`TChild`的实例,那么你需要调用该类的构造函数*:`TChild.Create`。 – 2009-07-20 19:30:30

回答

3

实际上有几种方法可以做到这一点,在你的父类中,创建你调用的虚拟方法,但这些方法什么都不做。在你的子类中,重写这些方法。这些方法可以很容易地得到保护,但它们必须存在于父项中。

type 
    TParent = class 
    protected 
    procedure SpecialProcessing; virtual; 
    public 
    procedure DoWork; 
    end; 

    TChild = class(TParent) 
    protected 
    procedure SpecialProcessing; override; 
    end; 

procedure TParent.DoWork; 
begin 
    SpecialProcessing; 
end; 

procedure TParent.SpecialProcessing; 
begin 
    // does nothing, placeholder 
end; 

procedure TChild.SpecialProcessing; 
begin 
    // do special work here 
end; 

我故意没做TParent。SpeciallProcessing摘要。这可以完成,但只有当TParent永远不会被直接创建,只有后代才会。抽象方法是一种未实现的方法,但被用作占位符以供后来的孩子使用。

要创建使用实例如下:

var 
    C : TParent; 
begin 
    // Create as a TChild, which is a TParent decendant 
    C := TChild.Create; 
    try 
    C.DoWork; 
    finally 
    C.Free; 
    end; 
end; 
2

这是不可能的。在子类中使用非公共方法的全部目的是防止类(除了子类)能够访问它们。试图解决这个问题违反了基本的面向对象的原则。

我会考虑重新考虑你的设计。

+0

如果您删除了答案的第一句话,那么我会进行最后的投票 - 显然,这些限制的解决方法非常有限。你的(优秀的)主要观点是这种机械化是一个迹象,表明存在设计问题。 – Argalatyr 2009-07-20 20:22:33

+0

有设计解决方法来解决需要做到这一点,但没有办法从父类中(这是原始问题)直接访问子类中的私有静态方法 - 因此我的评论是,这不是可能。 – 2009-07-20 20:28:51

3

你想做什么违反了继承原则Liskov Substitution。这可能有更好的方法。你到底想做什么?

编辑:

你为什么不能创建子类的对象实例。您始终可以将其分配给父类类型的变量。这通常以工厂模式完成。

0

您可以通过在创建子类时使用某种回调(父类为cattr,子类在定义时设置)来注册子类。

虽然这很少是正确的做法。像其他人所说,考虑一种不同的模式。

我不是德尔福的编码器,但你可以在父类上设置一个公共静态变量,并从子类中的设置方法中设置它。

在某些情况下(希望将消息传递给各种子类上的类设置方法),这是有道理的,但可能有更好的方法来执行您所需的操作。您可能希望更多地了解您的代码正在解决的问题。

1

我可能会丢失给谁已经回答了人们一些东西明显。但我认为这只是一个实例化正确对象的问题。

父代码将调用子代码,因为该对象是子类的实例。

试试这个

var c:TChild; 
begin 
    c := TChild.Create; 
    c.Initialize; 
    c.Free; 
end. 

甚至

var c:TParent; 
begin 
    c := TChild.Create; 
    c.Initialize; 
    c.Free; 
end.