Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi:在子类中使用来自主类的函数_Delphi - Fatal编程技术网

Delphi:在子类中使用来自主类的函数

Delphi:在子类中使用来自主类的函数,delphi,Delphi,在写作课的新的一面,我有一个小问题,我已经尝试研究,但仍然没有答案 我想创建一个类的实例,创建多个子类,创建自己的子类。其思想是在主程序中使用如下代码: procedure TForm1.Button1Click(Sender: TObject); var Temp : Integer; begin MainClass := TMainClass.Create(Form1); Temp := MainClass.SubClass1.SubSubClass1.SomeValue; en

在写作课的新的一面,我有一个小问题,我已经尝试研究,但仍然没有答案

我想创建一个类的实例,创建多个子类,创建自己的子类。其思想是在主程序中使用如下代码:

procedure TForm1.Button1Click(Sender: TObject);
var
  Temp : Integer;
begin
  MainClass := TMainClass.Create(Form1);
  Temp := MainClass.SubClass1.SubSubClass1.SomeValue;
end;
主类如下所示,在单独的文件中创建:

  TMainClass = class(TObject)
    private
      FSubClass1 : TSubClass1;
    public
      ValueFromAnySubClass : Integer;
      property SubClass1 : TSubClass1 read FSubClass1 write FSubClass1;
      procedure SetSomeValueFromMainClass(Value : Integer);
  end;
...
...
...
procedure TMainClass.SetSomeValueFromMainClass(Value : Integer);
begin
  ValueFromAnySubClass := Value;
end;
  TSubClass1 = class(TObject)
    private
      FSubSubClass1 : TSubSubClass1;
    public
      property SubSubClass1 : TSubSubClass1 read FSubSubClass1 write FSubSubClass1;
  end;
  TSubSubClass1 = class(TObject)
  private
    SomeValue : Integer;
    function  GetSomeValue : Integer;
    procedure SetSomeValue(Value : Integer);
  public
    property SomeValue : Integer read GetSomeValue write SetSomeValue;
  end;
...
...
...
procedure TSubSubClass1.SetSomeValue(Value : Integer);
begin
  SetSomeValueFromMainClass(Value); <<< Error Here <<<
end;
子类也在单独的文件中:

  TMainClass = class(TObject)
    private
      FSubClass1 : TSubClass1;
    public
      ValueFromAnySubClass : Integer;
      property SubClass1 : TSubClass1 read FSubClass1 write FSubClass1;
      procedure SetSomeValueFromMainClass(Value : Integer);
  end;
...
...
...
procedure TMainClass.SetSomeValueFromMainClass(Value : Integer);
begin
  ValueFromAnySubClass := Value;
end;
  TSubClass1 = class(TObject)
    private
      FSubSubClass1 : TSubSubClass1;
    public
      property SubSubClass1 : TSubSubClass1 read FSubSubClass1 write FSubSubClass1;
  end;
  TSubSubClass1 = class(TObject)
  private
    SomeValue : Integer;
    function  GetSomeValue : Integer;
    procedure SetSomeValue(Value : Integer);
  public
    property SomeValue : Integer read GetSomeValue write SetSomeValue;
  end;
...
...
...
procedure TSubSubClass1.SetSomeValue(Value : Integer);
begin
  SetSomeValueFromMainClass(Value); <<< Error Here <<<
end;
现在,对于另一个文件中的子类:

  TMainClass = class(TObject)
    private
      FSubClass1 : TSubClass1;
    public
      ValueFromAnySubClass : Integer;
      property SubClass1 : TSubClass1 read FSubClass1 write FSubClass1;
      procedure SetSomeValueFromMainClass(Value : Integer);
  end;
...
...
...
procedure TMainClass.SetSomeValueFromMainClass(Value : Integer);
begin
  ValueFromAnySubClass := Value;
end;
  TSubClass1 = class(TObject)
    private
      FSubSubClass1 : TSubSubClass1;
    public
      property SubSubClass1 : TSubSubClass1 read FSubSubClass1 write FSubSubClass1;
  end;
  TSubSubClass1 = class(TObject)
  private
    SomeValue : Integer;
    function  GetSomeValue : Integer;
    procedure SetSomeValue(Value : Integer);
  public
    property SomeValue : Integer read GetSomeValue write SetSomeValue;
  end;
...
...
...
procedure TSubSubClass1.SetSomeValue(Value : Integer);
begin
  SetSomeValueFromMainClass(Value); <<< Error Here <<<
end;

如何在我的子类中使用主类的函数和过程?

设计看起来非常糟糕。你肯定不想让所有这些课程都互相了解

当你看到一行代码中有不止一个的时候。操作员您应该问问自己代码是否在正确的类中。通常,这表示具有多个使用的代码行。应该在链的下一个类中

但是,如果要调用方法,则需要一个实例。你写道:

procedure TSubSubClass1.SetSomeValue(Value : Integer);
begin
  SetSomeValueFromMainClass(Value);
end;
当然,这不会编译。因为SetSomeValueFromMainClass不是TSUBClass1的方法。相反,SetSomeValueFromMainClass是TMainClass的一个方法。因此,要调用该方法,需要一个tmainlass实例

这意味着,如果你真的必须这样做,你需要为TSubSubClass1的每个实例提供一个TMainClass的实例。您可以在构造函数中提供它,并记下引用

当然,当您这样做时,您现在会发现您的类都是相互耦合的。在这一点上,人们可能会怀疑它们是否应该合并


我并不是说合并这些类是正确的设计。我不想就什么是正确的设计发表任何自信的声明。也许您需要的是一个接口,该接口承诺将实现setter作为解耦的手段。我真正有信心说的是,您当前的设计不是正确的设计。

使用另一个类的函数不需要子类。另外,您的示例代码根本没有使用子类。一个合适的子类可以自动访问其祖先的所有公共和受保护的函数

正如已经指出的,在你的设计中有严重的缺陷

此外,根据您的评论:

这些类都执行截然不同的功能,但在一天结束时需要将数据写入硬件。数据从硬件读取并保存在内存中以供使用,直到所有工作完成后将其写回硬件组件。主类中的过程负责在任何子类需要时将实时数据写入硬件

对于David的回答:您根本不需要子类

您所需要的只是硬件类上的一个公共方法。对于其他类的每个实例,都有一个对硬件类的正确实例的引用

type
  THardwareDevice = class(TObject)
  public
    procedure WriteData(...);
  end;

  TOtherClass1 = class(TObject)
  private
    FDevice: THardwareDevice;
  public
    constructor Create(ADevice: THardwareDevice);

    procedure DoSomething;
  end;


constructor TOtherClass1.Create(ADevice: THardwareDevice);
begin
  FDevice := ADevice;
end;

procedure TOtherClass1.DoSomething;
begin
  //Do stuff, and maybe you need to tell the hardware to write data
  FDevice.WriteData(...);
end;

//Now given the above you can get two distinct object instances to interact
//as follows. The idea can be extended to more "other class" types and instances.
begin
  FPrimaryDevice := THardwareDevice.Create(...);
  FObject1 := TOtherClass1.Create(FPrimaryDevice);
  FObject1.DoSomething;

  //NOTE: This approach allows extreme flexibility because you can easily
  //      reference different instances (objects) of the same hardware class.
  FBackupDevice := THardwareDevice.Create(...);
  FObject2 := TOtherClass1.Create(FBackupDevice);
  FObject2.DoSomething;

  ...
end;

据我所知,子类word通常用于继承概念,但您编写的代码是一些复合类。正如您可能看到的,Delphi中许多类的构造函数都有一个名为AOOwner的参数,该参数可能是TComponent或TObject或

如果您像下面一样定义TSubclass1和TSubSubClass1的构造函数,并将定义为属性的类的所有者更改为Self-in-set函数,则可以通过键入Owner属性来访问TMainClass

我对你的代码做了一点修改,让它可以按照你想要的方式工作,但我建议改变你的设计

  TSubSubClass1 = class(TObject)
  private
    FOwner: TObject;
    function GetSomeValue:Integer;
    procedure SetSomeValue(const Value: Integer);
    procedure SetOwner(const Value: TObject);
  public
    constructor Create(AOwner:TObject);reintroduce;
    property Owner:TObject read FOwner write SetOwner;
    property SomeValue : Integer read GetSomeValue write SetSomeValue;
  end;

  TSubClass1 = class(TObject)
  private
    FSubSubClass1: TSubSubClass1;
    FOwner:TObject;
    procedure SetSubSubClass1(const Value: TSubSubClass1);
    procedure SetOwner(const Value: TObject);
  public
    constructor Create(AOwner:TObject);reintroduce;
    property Owner:TObject read FOwner write SetOwner;
    property SubSubClass1 : TSubSubClass1 read FSubSubClass1 write SetSubSubClass1;
  end;

  TMainClass = class(TObject)
  private
    FSubClass1: TSubClass1;
    procedure SetSubClass1(const Value: TSubClass1);
  public
    ValueFromAnySubClass : Integer;
    constructor Create;
    property SubClass1 : TSubClass1 read FSubClass1 write SetSubClass1;
    procedure SetSomeValueFromMainClass(Value : Integer);
  end;
实施

{ TSubSubClass1 }

constructor TSubSubClass1.Create(AOwner: TObject);
begin
  Owner:=AOwner;
end;

function TSubSubClass1.GetSomeValue: Integer;
begin
  Result:=TMainClass(TSubClass1(Self.Owner).Owner).ValueFromAnySubClass;
end;

procedure TSubSubClass1.SetOwner(const Value: TObject);
begin
  FOwner := Value;
end;

procedure TSubSubClass1.SetSomeValue(const Value: Integer);
begin
  TMainClass(TSubClass1(Self.Owner).Owner).SetSomeValueFromMainClass(Value);
end;

{ TSubClass1 }

constructor TSubClass1.Create(AOwner: TObject);
begin
  Owner:=AOwner;
  FSubSubClass1:=TSubSubClass1.Create(Self);
end;

procedure TSubClass1.SetOwner(const Value: TObject);
begin
  FOwner := Value;
end;

procedure TSubClass1.SetSubSubClass1(const Value: TSubSubClass1);
begin
  FSubSubClass1 := Value;
  FSubSubClass1.Owner:=Self;
end;

{ TMainClass }

constructor TMainClass.Create;
begin
  FSubClass1:=TSubClass1.Create(Self);
end;

procedure TMainClass.SetSomeValueFromMainClass(Value: Integer);
begin
  ValueFromAnySubClass := Value;
end;

procedure TMainClass.SetSubClass1(const Value: TSubClass1);
begin
  FSubClass1 := Value;
  FSubClass1.Owner:=Self;
end;

您必须在实现的uses部分中输入正确的文件名。

从我给出的示例来看,设计可能很差,但实际上并没有那么差。这些类都执行截然不同的功能,但在一天结束时需要将数据写入硬件。数据从硬件读取并保存在内存中以供使用,直到所有工作完成后将其写回硬件组件。main类中的过程负责在任何子类需要时将实时数据写入硬件。@Cybotage您可能不认为您的设计很差,但实际上它非常差。事实上,您已经用高度抽象的概念描述了您的问题,因此不可能提出更好的设计。但是,您的评论表明,其他每个类都需要访问硬件类。更准确地说,是硬件类的一个实例。因此,正如David所建议的,一个明确的考虑是,其他每个类在创建时都应该被告知要使用哪个harware对象。这些不是子类。你这样描述他们并不能使他们如此。它们只是独立的类,无论出于何种原因,您似乎有意将它们耦合在一起。不幸的是,你在摘要中用不恰当的名字进行的描述不会得到任何人的认可
除了辩论之外的任何地方,这就是正在发生的事情。在我看来,你似乎误解了次级班的概念。子类从父类继承。您的代码中没有显示任何继承。@CraigYoung:正确。对于Cybotage:这些是包含类,即外部类包含内部类等,就像TForm派生类可以包含TEdit或TButton一样。它们绝对不是子类。只是术语混淆。由于没有更好的术语,我用错了,我道歉。至于设计,很遗憾,我不能透露更多细节。我知道这不是最好的,但比我接管的项目中目前实施的要好。谢谢你的评论。谢谢你的时间和努力。我将对此进行研究,以了解更多的课程。