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一样。它们绝对不是子类。只是术语混淆。由于没有更好的术语,我用错了,我道歉。至于设计,很遗憾,我不能透露更多细节。我知道这不是最好的,但比我接管的项目中目前实施的要好。谢谢你的评论。谢谢你的时间和努力。我将对此进行研究,以了解更多的课程。