【问题标题】:Overriding static fields for children in typescript在打字稿中覆盖子项的静态字段
【发布时间】:2021-02-14 16:23:07
【问题描述】:

我有一个包含静态 URL 的抽象类,并使用该静态 URL 实现功能。子级应覆盖 A 类的静态 URL。

但我仍然希望孩子们使用其父类 A 提供的功能来使用子类的静态覆盖 URL。有什么办法可以在 Typescript 中做到这一点?

interface IState {
    cashflowToPost?: CashflowObject;
    cashflowList: CashflowObject[];
}
export default abstract class CashflowListView extends React.Component<{}, IState> {
    static cashflowObject : CashflowObject;
    static getURL : URL;

    
    callApi() {
        try {
            axios.get(CashflowListView.getURL.toString()).then(response => {
                console.log("called Api");
                this.setState({cashflowList: response.data});
            })
        } catch {
            console.log("failed to call api!")
        }
    }
    


    componentDidMount() {
        this.callApi();
    }

    
}

【问题讨论】:

  • 考虑到每个类都应该附加一个 URL,所以基于类而不是基于实例,我认为静态是正确的方法吗?我只是希望孩子们在 axios 调用中使用他们自己的静态 url 而不是 CashflowListView.getURL.toString()
  • 你不能那样做。父级的方法将始终引用父级的静态变量。

标签: javascript typescript inheritance static


【解决方案1】:

嗯,我认为这是不可能的,直到我自己开始搜索它。这已经在这里回答了:Access child class' static members from base class

abstract class Base {
    static url: string = "hello.com";

    log() {
        const thisConructor = this.constructor as typeof Base;
        console.log('Do it>>>', thisConructor.url);
        // => Make axios call with "thisConructor.url"
    }
}

class Child extends Base {
    static url: string = "hello1.com";
}

const c = new Child();
c.log(); // => "hello1.com"

【讨论】:

    【解决方案2】:

    但我还是希望孩子们使用其父类 A 提供的功能来使用子类的静态覆盖 URL。

    子实例当然可以访问父类中的方法,但是如果父类的方法访问静态属性,从实例调用它会失败:

    class A {
      static getURL = 'http://example.com';
      
      aMethod() {
        console.log('A.aMethod() getURL:', getURL);
      }
    }
    
    class B extends A {
      static getURL = 'http://example.com/BClass';
    }
    
    const bInstance = new B();
    bInstance.aMethod(); // ReferenceError: Can't find variable: getURL
    

    虽然您不能“覆盖”类的静态变量,但您可以执行以下操作:

    class A {
      static getURL = 'http://example.com/AClass';
      
      // make the method static and pass in url
      static aMethod(url) {
        console.log('aMethod() url:', url);
      }
    }
    
    class B extends A {
      static getURL = 'http://example.com/BClass';
    }
    
    console.log('A.getURL:', A.getURL);
    A.aMethod(A.getURL);
    
    console.log('B.getURL:', B.getURL)
    B.aMethod(B.getURL);

    但由于 OP 希望重用引用静态属性 (getURL) 和实例属性 (this) 的实例方法,因此需要不同的策略。

    解决方案:从类构造函数访问静态属性

    幸运的是,我们可以利用static property can be referenced from the instance's class constructor:

       thisURL = this.constructor.getURL;
    

    this.constructor.getURL 引用实例类(而非父类)的静态属性 getURL。

    class A {
      static getURL = 'http://AClassURL';
    
      aInstanceMethod() {
        // `this.constructor.getURL` references the instance's class
        this.result = `result obtained using ${this.constructor.getURL}`;
      }
    }
    
    class B extends A {
      static getURL = 'http://BClassURL';
    }
    
    
    const aInstance = new A();
    aInstance.aInstanceMethod();
    
    const bInstance = new B();
    bInstance.aInstanceMethod();
    
    
    document.querySelector('pre').innerText =
      `A.getURL = ${A.getURL}
    B.getURL = ${B.getURL}
    
    aInstance: ${JSON.stringify(aInstance, null, 2)}
    
    bInstance: ${JSON.stringify(bInstance, null, 2)}`;
    &lt;pre&gt;&lt;/pre&gt;

    【讨论】:

    • 感谢您的回答。但是说我想要一个静态的 1 GB 图像而不是 URL,并将其保存为每个实例的字段会很慢。我为父类使用该静态图像编写了很多代码。我想为子类使用另一个静态图像。我是否必须在子类中使用父类中的大图像重写函数?
    • @Esnaj 查看我的更新答案,accesses static members via the class constructor。还有来自Kiran的答案。
    猜你喜欢
    • 2018-12-08
    • 2019-01-15
    • 2019-01-06
    • 1970-01-01
    • 2020-05-19
    • 2020-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多