【问题标题】:Add setter to property in descendant class将setter添加到后代类中的属性
【发布时间】:2012-09-29 20:53:18
【问题描述】:

我有两个 Delphi 课程。父类声明一个字符串字段 FSSN 和匹配的属性 SSN,访问器直接读取和写入该字段。在我的子类中,我想重新声明属性 SSN 以使用子类中的设置器(如果可能,在将 SSN 写入字段之前对其进行转换)。

属性 SSN 将由父类的方法设置,但是(如果实例是子类的实例)我希望调用 child 设置器。但是,当我运行代码时,我从不输入子设置器,并且该字段似乎是直接使用父级中的属性声明设置的。

这个可以吗?

(我意识到我可以通过在父类中引入 setter 过程并在子类中覆盖来实现这一点;如果可能的话,我宁愿不打扰父类)。

这是我目前所拥有的(当然是一个大大简化的版本):

TCustomPerson = class(TObject)
  protected
    FSSN: String;
  public
    procedure LoadFromXML(ANode: IXMLNode);
    property SSN: String read FSSN write FSSN;

TMyPerson = class(TCustomPerson)
  protected
    procedure SetSSN(ASSN: String);
  public
    property SSN: String read FSSN write SetSSN; // <=== Setter introduced.

 procedure TCustomPerson.LoadFromXML(ANode: IXMLNode);
 var ThisSSN: String;
 begin
    //extract SSN from XML into ThisSSN
    SSN := ThisSSN;                             // Expect to invoke SetSSN.
 end

procedure TMyPerson.SetSSN(ASSN: String);
begin
    FSSN := ValidateSSN(ASSN);                  // <== Breakpoint here never reached.
end

【问题讨论】:

  • 在重写方法的情况下(如您所指出的),父类将愉快地调用子类的代码。有没有办法虚拟化属性声明本身,以便在 setter-invocation 时父级将遵守子级的访问器规范?还是我只能通过重写的方法来处理这个问题?
  • +1,顺便说一句,一个写得很好的问题。 :-)
  • 重新考虑您的设计,您需要一个接受 TCustomPerson 类的 SSNValidator 类...

标签: delphi inheritance properties setter


【解决方案1】:

没有;这是不可能的。

子类可以访问父类,但是父类不知道子类,并且父类中没有任何可以使用多态性进行路由的东西被声明为虚拟。

在重写方法的情况下,有一个 VMT 可用于路由到正确的子类,但不能虚拟化没有 setter 的直接属性分配。您需要在父级中声明为虚拟的设置器,然后后代上的覆盖设置器将起作用。没有办法虚拟化直接的变量赋值。

【讨论】:

  • 谢谢。我会按照你的建议去做。
【解决方案2】:

我有一个使用 RTTI 的解决方法。您只需发布 SSN 属性。

 procedure TCustomPerson.LoadFromXML(ANode: IXMLNode);
 var ThisSSN: String;
 begin
    //extract SSN from XML into ThisSSN
    SetStrProp(Self,'SSN',ThisSSN);
 end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-25
    • 1970-01-01
    • 2016-11-12
    • 2017-02-14
    • 2011-11-26
    • 2018-03-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多