【问题标题】:Error when performing Inheritance in TypeScript在 TypeScript 中执行继承时出错
【发布时间】:2019-07-17 13:37:09
【问题描述】:

我一直在尝试理解打字稿中的继承

class user {
  name: string;
  email: string;

  constructor(name: string, email: string) {
    this.name = name;
    this.email = email;
  }

  checkUserData = id => {
    console.log(
      "This user name is" +
        this.name +
        "his email address is" +
        this.email +
        "and his ID is" +
        id
    );
  };
}

class college extends user {
  id: number;

  constructor(name, email, id) {
    super(name, email);
    this.id = id;
  }

  checkUserData = () => {
    super.checkUserData(this.id);
  };
}

let newUser: user = new college("Rohit Bhatia", "iro@gmail.com", 4556);

console.log(newUser.checkUserData());

这是我的代码,这里我收到以下错误

index.ts:31:11 - 错误 TS2340:只有公共和受保护的方法 基类可以通过 'super' 关键字访问。

31 super.checkUserData(this.id); ~~~~~~~~~~~~~~~~

index.ts:37:13 - 错误 TS2554:预期 1 个参数,但得到 0。

37 控制台.log(newUser.checkUserData()); ~~~~~~~~~~~~~~~~~~~~~~~

index.ts:10:19 10 校验用户数据 = id => { ~~ 没有提供“id”的参数

在我的代码中,我没有看到 private method 的用法,那么为什么会出现该错误?另外,我知道我的代码有很多错误,有人可以帮我修复它吗?

我的意图是什么?

继承类用户, 在父类中创建一个新的属性 checkUserData(认为这是一个公共类),它以 ID 作为参数, 从一个子类调用该类并将 id 传递给它。

【问题讨论】:

  • 您正在使 checkUserData 成为函数值属性而不是方法。它们不一样。试试checkUserData(id: number) { /* impl */ } 而不是checkUserData = id => { /* impl */ }
  • 对于第二个问题,不要将newUser 注释为user,然后尝试不带参数调用其checkUserData() 方法,因为user.checkUserData() 需要一个参数。您需要将其注释为let newUser: college 或只是let newUser = new college(...)。一旦你将newUsercollege 扩大到user,编译器就不再知道它是college 并且不会让你调用college 特定的方法。
  • 通常情况下,每个问题只处理一个主题时效果最好……“帮助我解决所有这些问题”对提问者有帮助,但对后来的人没有多大帮助。因此,如果您有多个问题,您可能应该打开多个问题。
  • 如果这些 cmets 中的任何一个对我有帮助,我可能会在使用真正的计算机时将它们充实为答案(否则,如果其他人决定在我之前做出真正的答案,我不会被冒犯)
  • 我部分明白了你所说的,你能详细解释一下你想表达什么吗?

标签: typescript


【解决方案1】:

这感觉像是两个不同的问题,但我会在这里回答它们:


我将如何更改您的代码:

// non-primitive types should start with a capital letter by convention
class User {
  name: string;
  email: string;

  constructor(name: string, email: string) {
    this.name = name;
    this.email = email;
  }

  // a method on the prototype, not an instance property
  checkUserData(id: number) {
    console.log(
      "This user name is" +
      this.name +
      "his email address is" +
      this.email +
      "and his ID is" +
      id
    );
  };
}


// non-primitive types should start with a capital letter by convention
class College extends User {
  id: number;

  // annotate types on function parameters
  constructor(name: string, email: string, id: number) {
    super(name, email);
    this.id = id;
  }

  // a method on the prototype, not function property
  checkUserData() {
    super.checkUserData(this.id);
  };
}

// do not widen to user type, let the compiler infer as college
let newUser = new College("Rohit Bhatia", "iro@gmail.com", 4556);

console.log(newUser.checkUserData());

注意:按照惯例,非原始类型以大写字母开头,因此我将user 更改为User,将college 更改为College。使用小写的类名并不是无效,但它违反了预期。如果需要,请随意将它们保留为小写。


问题一:“为什么我不能打电话给super?”

答案一:您使用的是函数属性而不是方法。改用方法。

详细信息:我已将UserCollege 中的checkUserData() 更改为prototype method。这意味着它们被添加到User.prototypeCollege.prototypeUserCollege 的实例只是通过prototypical inheritance 继承它们。现在您可以在College.prototype.checkUserData() 中使用thissuper。你定义方法的方式,如arrow functions,这是不可能的。箭头函数没有自己的 thissuper 上下文,UserCollege 的每个实例都将获得箭头函数的 own 副本,因此您无法通过原型继承覆盖它.箭头函数(正如它在MDN docs 中所说)不适合作为方法。


问题二:“为什么newUser.checkUserData()给我一个错误?”

答案二:您已声明 newUser 的类型为 User。不加注释,或者将其声明为College 类型。

详细信息:当您说let newUser: User = ... 时,您是在告诉编译器它是User,即使您知道它,编译器也不会尝试确定它是否是更具体的类型,例如College是一个。由于User 实例需要其checkUserData() 方法来获取单个参数,因此您将收到错误消息。解决这个问题的方法是让编译器知道newUser 实际上是College。您可以通过注释 (let newUser: College = ...) 显式执行此操作,或者您可以省略注释并通过查看 new College(...) 的返回类型让编译器 infer 认为它是 College 实例。


好的,希望对您有所帮助。祝你好运!

【讨论】:

    猜你喜欢
    • 2010-12-07
    • 1970-01-01
    • 2016-11-18
    • 2014-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多