是否可以在delphi类上定义虚拟静态成员?

时间:2013-07-27 10:12:58

标签: delphi oop virtual delphi-xe static-members

我需要创建类似于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.

干杯:)

2 个答案:

答案 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;