如何在构造函数的重载函数中使用子类中的字段值

Posted

技术标签:

【中文标题】如何在构造函数的重载函数中使用子类中的字段值【英文标题】:How to use field value from subclass in overloaded function in constructor 【发布时间】:2021-09-03 01:26:21 【问题描述】:

这段代码可以说明问题:

class A

    public readonly x;
    
    constructor()
    
        this.x = this.getX();
    

    protected getX()
    
        return "X";
    


class B extends A

    public readonly suffix = ko.observable("will change later");

    constructor()
    
        super();        
    

    protected getX()
    
        return super.getX() + " " + this.suffix();
    


console.log(new B().x);

结果是“X undefined”,这显然是不受欢迎的,尽管考虑到 TypeScript 的“构造工作流程”是可以预期的——主要是字段 suffix 仅在超级构造函数完成后才获得其值。但这是为什么呢?也许是因为在声明它时我们可以在“超级”实际存在之前使用“超级”?是“鸡对蛋”的原则吗?

不幸的是,我多次遇到这个问题,有时我不得不重新设计一些东西来解决这个问题。如何解决这种“早期现场使用”?有什么已知的模式吗?

【问题讨论】:

【参考方案1】:

当前仅在完成super 呼叫后分配本地成员的方法看起来与您的课​​程无关。但它对于覆盖祖先成员的类来说非常重要。

class A  x = 1 
class B extends A  x = 2 

分配this.x = 2 之前 super 调用将导致非常不幸的后果。

我并不完全了解此类问题的惯用解决方案。但是getters/setters 看起来很适合最近可以初始化的类成员。

class A 
    public get x(): string  // implements readonly as it has no setter
        return this.getX()
    

    protected getX(): string 
        return "X";
    


class B extends A 
    public readonly suffix = "will change later";

    constructor() 
        super();        
    

    protected getX() 
        return super.getX() + " " + this.suffix;
    


console.log(new B().x); // "X will change later"

playground link

【讨论】:

这种getter方法是一个绝妙的主意,正好为我解决了这类问题。更准确地说,根据设计,getX 方法应该只调用一次,所以我想将它存储在只读字段中。但现在我将拥有 getter,并在那里返回缓存值。 playground link

以上是关于如何在构造函数的重载函数中使用子类中的字段值的主要内容,如果未能解决你的问题,请参考以下文章

在c++中的继承,如何在子类中重载成员函数

对虚函数进行重载是啥意思?

关于C++子类构造函数的重载问题

为啥我能够为 QObject 子类创建复制构造函数并重载赋值运算符?

逆向第十九讲——类继承和成员类运算符重载模板逆向20171211

派生类中的重载构造函数