【问题标题】:Typescript: How to call method defined with arrow function in base class using super keyword in child class?Typescript:如何在子类中使用 super 关键字调用基类中用箭头函数定义的方法?
【发布时间】:2014-06-06 18:58:19
【问题描述】:

给定

class BaseClass{

  count:number=0;

  public someMethod=():void =>{
      this.count++;
  }
}

class ChildClass extends BaseClass{
  public someMethod=():void=>{
     super.someMethod();
     //Do more work here.
  }
}

我收到错误消息:

只有基类的公共方法可以通过“super”访问 关键字。

@Basarat 在这里提供了一些信息,但这似乎是对该语言的真正破解。 typescript arrow operator to define a function on prototype

如何在保留“this”的上下文使用的同时做到这一点?

我是否正确使用箭头函数,或者它们真的应该仅用作声明回调之类的方法?

【问题讨论】:

  • 我相信你已经知道了......但仍然想分享(因此评论:youtube.com/watch?v=tvocUcbCupA&hd=1
  • 我试图理解你为什么要以这种方式使用箭头函数。为什么不能在原型上使用常规方法是有原因的吗?
  • @web2nr 这个问题源于#Angular 的使用,我的对象的一些方法最终成为回调。因为回调在我自己的代码中并不明显(我自己的代码中没有使用call),所以我发现this 的上下文并不一致。我以为我可以简单地在我的类中的任何地方使用箭头函数,因此对我的类的回调就可以正常工作,并且从 Angular 的角度来看它确实如此。不过,正如我发现的那样,这使我无法使用#Typescript 继承。我认为在实践中我必须有选择性地使用箭头函数。
  • @RichardCollette 我认为这是您发现的 TypeScript 的一个合理缺陷。它不应该提供类,除非方法中的this 总是 是类实例。回调不是借口,因为它们可以而且应该使用顶级函数来实现。我已经学会了使用胖箭头语法,直到我需要覆盖方法。错误提交,但我怀疑它会被视为“设计”而被驳回。 typescript.codeplex.com/workitem/2491

标签: typescript arrow-functions


【解决方案1】:

为了争论,假设你

  • 正在使用粗箭头语法,因为这些方法是由 UI 事件或回调(在我的情况下为敲除点击事件)触发的
  • 需要继承来消除 UI(或回调)响应代码中的冗余。

一个最低限度的hackish(如果不是优雅)的答案是将你的函数分成两个调用来解决这两个问题:

Class A {
    public handleScope = () => {
        return this.handleInheritance();
    }

    public handleInheritance() {
        // do work
    }
}

Class B extends A {
    public handleInheritance() {
         super.handleInheritance() // super works here
         // additional work
    }
}

我是第一个承认加倍功能是“丑陋”的人,但恕我直言,比我见过的其他选项要丑得多。为了帮助标准化命名,我将单行“作用域”函数命名为基本函数的名称(例如myFunction)加上“Scoper”(即myFunctionScoper)。这也是 IDE 友好的,因为当您开始键入可继承方法的名称时,您通常会得到 Scoper 方法作为提示选项。

【讨论】:

  • 如此优雅的解决方案。谢谢!
【解决方案2】:

只是想从这里的另一个讨论中捕捉到这个问题的“答案”: https://typescript.codeplex.com/workitem/2491

在内存或处理开销方面肯定效率不高,但它确实回答了这个问题。

class Base {
    x = 0;
    constructor() {
        for (var p in this)
            if (!Object.prototype.hasOwnProperty.call(this, p) && typeof this[p] == 'function') {
                var method = this[p];
                this[p] = () => { method.apply(this, arguments); };
                // (make a prototype method bound to the instance)
            }
    }
}

class A extends Base {
    doSomething(value) { alert("A: " + value + " / x == " + this.x); }
}

class B extends A {
    doSomething(value) { alert("B: " + value + " / x == " + this.x ); super.doSomething(value); }
}

var b = new B();
var callback = b.doSomething;
callback("Cool!");

【讨论】:

    【解决方案3】:

    如果原型中没有函数实现,派生类就无法“找到”基类实现。你可以把它分开,这样你就有一种方法可以保存this,另一种方法可以通过super使用:

    class BaseClass {
      count: number = 0;
    
      someMethodImpl() {
        this.count++;
      }
    
      public someMethod = this.someMethodImpl;
    }
    
    class ChildClass extends BaseClass {
      public someMethod = (): void=> {
        super.someMethodImpl();
        //Do more work here.
      }
    }
    

    【讨论】:

      【解决方案4】:

      箭头函数是正确的,还是应该只用作声明回调之类的方法?

      它们实际上应该只用于回调。如果你想要一个类层次结构,那么使用原型。 prototype 还可以节省内存。

      强制修复:只有一个this,它是当前实例。如果您在子类中覆盖this.foo,则基实例this.foo 将丢失。在构造函数中保留基本版本

      class BaseClass{
      
        count:number=0;
      
        public someMethod=():void =>{
            this.count++;
        }
      }
      
      class ChildClass extends BaseClass{
      
        constructor(){      
            super();
            var baseSomeMethod = this.someMethod;
            this.someMethod = ()=>{
                // implement here 
            }
        }
      
      }
      

      【讨论】:

      • class Parent{ public foo=():void =>{ //stuff } } class Child extends Parent{ constructor(){ super(); var superFoo = this.foo; this.foo = ()=>{ superFoo(); } } }
      • 我认为添加代码的准系统箭头函数继承重构会很有帮助,语言参考父级和超级级。对于那些试图绘制平行线的人来说,这里可能更容易看到。
      猜你喜欢
      • 2019-12-24
      • 2012-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-08
      • 2012-08-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多