我需要创建类似于PHP语言实现的东西。
假设我创建了一个定义2个静态成员变量的基类,然后子类应该能够“覆盖”它们,所以如果我在BaseClass中定义了静态变量“someStatic”,那么我将子类化为DerivedClass ,当我调用TDerivedOne.someStatic时,该程序应该从该派生类中显示someStatic ..但这不是Delphi的情况,我肯定是错误地实现了它。
目前,我实现了另一种设计方法,其中变量未声明为静态,然后创建一个名为“setup”的虚拟抽象方法,然后在BaseClass构造函数上调用此设置,但此设计需要在我们可以检索所需的变量之前首先创建的对象。
现在出于好奇,我想知道是否可以实现虚拟静态变量来保存“几个打字......”
以下是问题的代码段
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
TBaseClass = class
protected
class var someStatic: string;
public
class function get: string; virtual;
end;
TDerived = class( TBaseClass )
(*
//if i uncomment this section, then the print bellow will print the Base's static var
protected
class var someStatic: string;
*)
end;
TDerived2 = class( TBaseClass )
end;
class function TBaseClass.get: string;
begin
Result := someStatic;
end;
begin
// ------If the class is defined per unit, this one should be on the initialization section
TBaseClass.someStatic := 'base';
TDerived.someStatic := 'derived';
TDerived2.someStatic := 'derived2';
// ------END OF INITIALIZATION
try
//i'm expecting this would print 'derived' but it prints 'derived2' :'(
//i am using DelphiXE
//apparently delphi treat the statics differently from that of php's
writeln( TDerived.get );
readln;
except
on E: Exception do
writeln( E.ClassName, ': ', E.Message );
end;
end.
干杯:)
答案 0 :(得分:2)
没问题,只要您覆盖Get
方法:
program Project1;
{$APPTYPE CONSOLE}
type
TBase = class
protected
class var FSomething: String;
class function Get: String; virtual;
end;
TDerived1 = class(TBase)
protected
class var FSomething: String;
class function Get: String; override;
end;
TDerived2 = class(TBase);
class function TBase.Get: String;
begin
Result := FSomething;
end;
class function TDerived1.Get: String;
begin
Result := FSomething;
end;
begin
TBase.FSomething := 'Base';
TDerived1.FSomething := 'Derived1';
TDerived2.FSomething := 'Derived2';
WriteLn(TDerived1.Get);
ReadLn;
end.
为了便于阅读,我建议重命名TDerived1
中的私有字段。
或者,使用class property
:
program Project1;
{$APPTYPE CONSOLE}
type
TBase = class
private
class var FSomething: String;
public
class property Something: String read FSomething write FSomething;
end;
TDerived1 = class(TBase)
private
class var FAnotherThing: String;
public
class property Something: String read FAnotherThing write FAnotherThing;
end;
TDerived2 = class(TBase);
begin
TBase.Something := 'Base';
TDerived1.Something := 'Derived1';
TDerived2.Something := 'Derived2';
WriteLn(TDerived1.Something);
ReadLn;
end.
答案 1 :(得分:0)
由于所有遗产中的SomeStatic指向同一个地方,因此将保留最后一个设置 最接近您要求的方法可能如下所示。
type
TBaseClass = class
protected
class var someStatic: string;
public
class function get: string; virtual;
class Procedure _Set(const Value:String);virtual;
end;
TDerived = class( TBaseClass )
protected
class var someStatic: string;
public
class function get: string; override;
class Procedure _Set(const Value:String);override;
end;
TDerived2 = class( TBaseClass )
protected
class var someStatic: string;
public
class function get: string; override;
class Procedure _Set(const Value:String);override;
end;
class function TBaseClass.get: string;
begin
Result := someStatic;
end;
{ TDerived }
class function TDerived.get: string;
begin
inherited;
Result := someStatic;
end;
class procedure TDerived._Set(const Value: String);
begin
SomeStatic := Value;
end;
{ TDerived2 }
class function TDerived2.get: string;
begin
inherited;
Result := someStatic;
end;
class procedure TDerived2._Set(const Value: String);
begin
SomeStatic := Value;
end;
class procedure TBaseClass._Set(const Value: String);
begin
SomeStatic := Value;
end;