В TypeScript интерфейс может расширить класс, для чего?
на Руководство По Машинописи в разделе "использование класса в качестве интерфейса" приведен пример интерфейса, который расширяет класс.
class Point { ... }
interface Point3d extends Point {...}
когда это может быть полезно? У вас есть практические примеры?
3 ответов
Я только что узнал об этой функции, но один из способов, которым это было бы полезно, заключается в том, что вы можете запрограммировать интерфейс без необходимости писать отдельный явный интерфейс.
учитывая класс:
class MyClass {
public get Something(): number { return this.mSomething; }
constructor(
private mSomething: number
) {
}
public DoSomething() {
// whatever
}
}
определите свой интерфейс автоматически. Это также дает вам только одно изменение, так как изменение вашего класса автоматически изменит ваш интерфейс:
interface IMyClass extends MyClass { }
Теперь вы можете использовать интерфейс вместо класса, что делает ваш код намного больше широко применимо:
// forces clients to use your class
public SomeFunctionSomewhereElse(something: MyClass) {
}
// now the client can use your class, or any other class with the same interface
// even ones that haven't been written yet
public SomeFunctionSomewhereElse2(something: IMyClass) {
}
Я думаю, что это не так полезно, как это может быть на некоторых других языках, хотя, поскольку в TypeScript, вы можете просто привести к любому типу, который вы хотите в любом случае.
возьмите этот класс, например:
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
}
}
вы можете создать экземпляр вот так:
let a1 = new MyClass(4, "hey");
но вы также можете создать объект, который удовлетворяет такому же точному интерфейсу, как:
let a2 = {
num: 3,
str: "hey",
fn: function(arr: any[]): boolean {
// do something
}
}
The 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) { ... }
как описано в раздел интерфейсов руководства TypeScript:
интерфейсы наследовать даже частные и защищенные члены базового класса. Это означает, что при создании интерфейса, который расширяет класс с частными или защищенными членами, этот тип интерфейса может быть реализован только этим классом или его подклассом.
такое ограничение представляется побочным эффектом частная и защищенные члены наследования.
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
}
}