在 Typescript 中实现接口时如何定义私有属性?
Posted
技术标签:
【中文标题】在 Typescript 中实现接口时如何定义私有属性?【英文标题】:How to define a private property when implementing an interface in Typescript? 【发布时间】:2016-10-14 00:02:18 【问题描述】:我在我的项目中使用 TypeScript,但遇到了一个问题。 我正在定义这样的接口:
interface IModuleMenuItem
name: string;
我想创建一个从此接口实现的类,但我希望名称是这样的私有属性:
class ModuleMenuItem implements IModuleMenuItem
private name: string;
我收到以下错误:
类 ModuleMenuItem 错误地实现了接口 IModuleMenuItem。 属性名称在 ModuleMenuItem 类型中是私有的,但在类型中不是私有的 IModuleMenuItem。
在实现接口时如何将属性定义为私有或受保护?
【问题讨论】:
接口基本上是在这里定义什么是公共的。我不确定你有没有办法检查什么是私有的。 【参考方案1】:接口定义了“公共”契约,因此在接口上使用protected
或private
访问修饰符是没有意义的,我们称之为实现细节。出于这个原因,你不能用一个界面做你想做的事。
如果您想让属性对消费者只读,但在子类中可覆盖,那么您可以执行以下操作:
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";
【讨论】:
那么交易是什么?我的意思是它很愚蠢,它破坏了接口的全部意义。 @Pachu 对我来说,这就是接口的全部意义所在。它定义了一个实现“符合”的public合约,并且外部组件可以使用而无需关心它是如何实现的。您所追求的是更加强制的实现行为,这是通过大多数语言中的抽象基类来实现的。 有人能告诉 TypeScript 的创建者吗?显然它在定义接口时包括私有成员。 :( @theMayer 不是必需的。您可以使用抽象类来实现接口并创建另一个类来扩展该类。这种实现方法称为复合。尽管您必须使用受保护而不是私有,因为私有无法重新实现。 也添加了答案。还不如有。【参考方案2】:我想你可以这样做
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
【讨论】:
我认为这更好,因为我们可以将它与 getter setter 一起使用。公认的解决方案使用getProp()
,这也很好,但是 getter setter 使代码更简洁。
这对任何人都有什么作用? this
甚至没有在构造函数中使用。【参考方案3】:
你可以拥有一个内部状态并为其分配接口而不是类并使该状态私有的唯一方法
class A
private state:IA = ...
【讨论】:
【参考方案4】:改用抽象类。
组合优于继承。
interface AppInterface
app: express.Application
port: string | number
abstract class AbstractApp implements AppInterface
app: express.Application
port: string | number
constructor()
this.app=express()
this.port=8080
protected defaultMiddlewares(): void
class App extends AbstractApp
constructor()
super()
protected defaultMiddlewares(): void
this.app.use(express.json())
【讨论】:
你到底在创作什么?抽象类是继承而不是组合 @mathiasbn en.wikipedia.org/wiki/Composition_over_inheritance【参考方案5】:如果类中有私有字段,您需要为该字段引入 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
...
TypeScript 会理解这个模型是正确实现的接口,因为我们已经引入了 set 和 get 方法。
【讨论】:
【参考方案6】:作为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$;
【讨论】:
以上是关于在 Typescript 中实现接口时如何定义私有属性?的主要内容,如果未能解决你的问题,请参考以下文章