在 Typescript 中实现接口时如何定义私有属性?

IT技术 reactjs typescript
2021-04-18 13:02:53

我在我的项目中使用 TypeScript,但遇到了一个问题。我正在定义一个这样的接口:

interface IModuleMenuItem {
    name: string;
}

我想创建一个从这个接口实现的类,但我希望名称是这样的私有属性:

class ModuleMenuItem implements IModuleMenuItem {
    private name: string;
}

我收到以下错误:

类 ModuleMenuItem 错误地实现了接口 IModuleMenuItem。属性名称在 ModuleMenuItem 类型中是私有的,但在 IModuleMenuItem 类型中不是私有的。

实现接口时如何将属性定义为私有或受保护的?

6个回答

接口定义了“公共”契约,因此在接口上拥有protectedprivate访问修饰符是没有意义的,我们称之为实现细节。出于这个原因,你不能用接口做你想做的事。

如果您想让该属性对消费者只读,但可以在子类中覆盖,那么您可以执行以下操作:

interface IModuleMenuItem {
     getName(): string;
}

class ModuleMenuItem implements IModuleMenuItem {
    private name;

    public getName() {
        return name;    
    }

    protected setName(newName : string) {
        name = newName;
    }
}

我认为在 TypeScript 2.0(尚未发布)中,readonly如果您在初始化时只读字段之后使用访问修饰符 - https://basarat.gitbooks.io/typescript/content/docs/types/readonly.html

interface IModuleMenuItem {
     readonly name : string;
}

class ModuleMenuItem implements IModuleMenuItem {
    public readonly name : string;

    constructor() {
        name = "name";
    }
}
那么交易是什么?我的意思是它只是愚蠢,它破坏了界面的全部意义。
2021-05-29 13:02:53
还添加了一个答案。也可能有。
2021-05-29 13:02:53
@Pachu 对我来说,这就是接口的全部意义所在。它定义了一个公共契约,一个实现“符合”并且一个外部组件可以在不关心它是如何实现的情况下使用它。您所追求的是更强制的实现行为,这是通过大多数语言中的抽象基类实现的。
2021-06-12 13:02:53
有人可以告诉 TypeScript 的创建者吗?显然,它在定义接口时包括私有成员。:(
2021-06-16 13:02:53
@theMayer 这不是必需的。您可以使用抽象类来实现接口并创建另一个类来扩展该类。这种实现方法称为复合。尽管您必须使用 protected 而不是 private,因为 private 无法重新实现。
2021-06-16 13:02:53

我想你可以这样做

interface IModuleMenuItem{
    name: string
}

class ModuleMenuItem implements IModuleMenuItem {
    private _name: string;
    constructor() {
    _name = "name";
    }

    get name(){
    // your implementation to expose name
    }

    set name(value){
    // your implementation to set name         
    }
 }
这对任何人都有什么作用? this甚至没有在构造函数中使用。
2021-06-06 13:02:53
我认为这更好,因为我们可以将它与 getter setter 一起使用。公认的解决方案使用getProp()这也很好,但 getter setter 使代码更简洁。
2021-06-14 13:02:53

如果类中有私有字段,则需要为该字段引入 setter 和 get 方法,如下所示:

export class Model {
    private _field: number;

    get field(): number {
        return this._field;
    }

    set field(value: number) {
        this._field= value;
    }
}

然后像往常一样创建接口(我们不能对接口字段使用私有修饰符),如下所示:

export interface IModel {
 field: number;
}

然后像这样在我们的类中实现它:

export class Model implements IModel {
...
}

由于我们引入了 set 和 get 方法,TypeScript 会理解这个模型是正确实现的接口。

您可以拥有内部状态并为其分配接口而不是类并将该状态设为私有的唯一方法

class A{
  private state:IA = ...
}

作为Syntax响应的附录,不需要包含 setter。只需要一个 getter 方法。例如,这可以用于在初始化时设置的只读变量,但我认为readonly在这种情况下最好使用修饰符。

interface IModuleMenuItem
{
    name: string;
}

class ModuleMenuItem implements IModuleMenuItem{
    private name$: string;

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

    public get name()
    {
        return this.name$;
    }
}