zur*_*aff 19 inheritance interface typescript
在 "使用类作为接口"部分的TypeScript手册中,有一个扩展类的接口示例.
class Point { ... }
interface Point3d extends Point {...}
这什么时候有用?你有这方面的实际例子吗?
Nit*_*mer 11
以这堂课为例:
class MyClass {
public num: number;
public str: string;
public constructor(num: number, str: string) {
this.num = num;
this.str = str;
}
public fn(arr: any[]): boolean {
// do something
}
}
Run Code Online (Sandbox Code Playgroud)
您可以像这样创建一个实例:
let a1 = new MyClass(4, "hey");
Run Code Online (Sandbox Code Playgroud)
但是你也可以创建一个满足相同精确界面的对象,如下所示:
let a2 = {
num: 3,
str: "hey",
fn: function(arr: any[]): boolean {
// do something
}
}
Run Code Online (Sandbox Code Playgroud)
的a1是instanceof MyClass,虽然a2仅仅是一个对象,但它们都实现了相同的接口.
扩展类的接口就是这样,你可以采用类定义和扩展它的接口.
也许这只是一种可能性,因为语言的性质,但这里有一个可能有用的例子:
class Map<T> {
private _items: { [key: string]: T };
set(key: string, value: T) { ... }
has(key: string): boolean { ... }
get(key: string): T { ... }
remove(key: string): T { ... }
}
interface NumberMap extends Map<number> {}
interface StringMap extends Map<string> {}
interface BooleanMap extends Map<boolean> {}
function stringsHandler(map: StringMap) { ... }
Run Code Online (Sandbox Code Playgroud)
小智 8
接口甚至继承基类的私有成员和受保护成员.这意味着当您创建一个扩展具有私有或受保护成员的类的接口时,该接口类型只能由该类或其子类实现.
这种限制似乎是私人和受保护成员继承的副作用.
class Parent
{
private m_privateParent;
}
interface ISomething extends Parent
{
doSomething(): void;
}
class NoonesChild implements ISomething
{
/**
* You will get error here
* Class 'NoonesChild' incorrectly implements interface 'ISomething'.
* Property 'm_privateParent' is missing in type 'NoonesChild'
*/
doSomething()
{
//do something
}
}
class NoonesSecondChild implements ISomething
{
/**
* Nope, this won't help
* Class 'NoonesSecondChild' incorrectly implements interface 'ISomething'.
* Types have separate declarations of a private property 'm_privateParent'.
*/
private m_privateParent;
doSomething()
{
//do something
}
}
class ParentsChild extends Parent implements ISomething
{
/**
* This works fine
*/
doSomething()
{
//Do something
}
}
Run Code Online (Sandbox Code Playgroud)
小智 6
我也很难理解“你为什么要这样做?” 这是我学到的。
如前所述,接口甚至继承基类的私有成员和受保护成员。这意味着当您创建一个接口来扩展具有私有或受保护成员的类时,该接口类型只能由该类或其子类实现。
想象一下,您正在为用户界面实现控件。您需要标准控件,例如按钮、文本框和标签。
层次结构将是:
class Control{
private state: any;
}
class Button extends Control{
}
class TextBox extends Control{
}
class Label extends Control{
}
Run Code Online (Sandbox Code Playgroud)
注意 Control 中的私有状态值。那会很重要。
现在假设我们想要一种方法来引用可以由某些激活触发的控件。例如,可以单击一个按钮。当您输入文本并按 Enter 键时,可以激活文本框。然而,标签是装饰性的,所以用户不能用它做任何事情。
我们可能想要一种引用此类控件的方法,以便我们可以仅对这些类型的控件执行某些操作。例如,我们可能想要一个接受控件作为参数的函数,但我们只想要可以激活的控件。
假设我们试图用一个不扩展类的简单接口来描述这些控件(这是不正确的,但我稍后会解释原因)。
// WARNING: This isn't correct - see rest of post for details.
interface ActivatableControl{
activate(): void;
}
Run Code Online (Sandbox Code Playgroud)
任何实现该接口的东西都可以被视为一个 ActivatableControl,所以让我们更新我们的层次结构:
class Control{
private state: any;
}
interface ActivatableControl{
activate(): void;
}
class Button extends Control implements ActivatableControl{
activate(){}
}
class TextBox extends Control implements ActivatableControl{
activate(){}
}
class Label extends Control{}
Run Code Online (Sandbox Code Playgroud)
如上所述,Label 没有实现 ActivatableControl。所以一切都很好,对吧?
这是问题 - 我可以添加另一个实现 ActivatableControl 的类:
class Dishwasher implements ActivatableControl{
activate(){}
}
Run Code Online (Sandbox Code Playgroud)
该界面的目的是用于可以激活的控件,而不是用于不相关的对象。
所以我真正想要的是指定一个需要某些控件才能激活的界面,而不是其他任何东西。
为了做到这一点,我让我的界面扩展 Control,如下所示:
class Control{
private state: any;
}
interface ActivatableControl extends Control {
activate(): void;
}
Run Code Online (Sandbox Code Playgroud)
由于 Control 具有私有值,因此只有 Control 的子类可以实现 ActivatableControl。
现在,如果我尝试这样做:
// Error!
class Dishwasher implements ActivatableControl{
activate(){}
}
Run Code Online (Sandbox Code Playgroud)
我会收到 Typescript 错误,因为 Dishwasher 不是 Control。
附加说明:如果一个类扩展了 Control,并实现了 activate,那么它可以被视为一个 ActivatableControl。本质上,即使没有显式声明接口,该类也实现了接口。
所以下面 TextBox 的实现仍然让我们把它当作一个 ActivatableControl:
class TextBox extends Control {
activate(){}
}
Run Code Online (Sandbox Code Playgroud)
所以这是层次结构的最终版本,其中一些代码显示了我可以用它做什么:
class Control {
private state: any;
}
interface ActivatableControl extends Control {
activate(): void;
}
class Button extends Control implements ActivatableControl {
activate() { }
}
// Implicitly implements ActivatableControl since it matches the interface and extends Control.
class TextBox extends Control {
activate() { }
}
class Label extends Control {
}
// Error - cannot implement ActivatableControl because it isn't a Control
/*
class Dishwasher implements ActivatableControl {
activate() { }
}
*/
// Error - this won't work either.
// ActivatableControl extends Control, and therefore contains state as a private member.
// Only descendants of Control can implement ActivatableControl.
/*
class Microwave implements ActivatableControl {
private state: any;
activate() { }
}
*/
let button: Button = new Button();
let textBox: TextBox = new TextBox();
let label: Label = new Label();
let activatableControl: ActivatableControl = null;
// I can assign button to activatableControl.
activatableControl = button;
// Same with textBox since textBox fulfills the contract of an ActivatableControl.
activatableControl = textBox;
// Error - label does not implement ActivatableControl
// nor does it fulfill the contract.
//activatableControl = label;
function activator(activatableControl: ActivatableControl){
// I can assume activate can be called
// since ActivatableControl requires that activate is implemented.
activatableControl.activate();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9739 次 |
| 最近记录: |