typescript 打字稿多重继承

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40807808/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 07:29:36  来源:igfitidea点击:

Typescript multiple inheritance

typescriptmultiple-inheritance

提问by Vayrex

I'm need of multiple inheritance in typescript. Logically it is not good to put a lot of functionality to hierarchy. I have one base class and number of hierarchy branches. But I need somehow to use mixings to put some main logic in separate classes, cuz it is not used in every branch.

我需要打字稿中的多重继承。从逻辑上讲,将很多功能放在层次结构中并不好。我有一个基类和多个层次结构分支。但是我需要以某种方式使用混合将一些主要逻辑放在单独的类中,因为它不是在每个分支中都使用。

UPDATE of code exmple:

代码示例的更新:

function Mixin = function(mixins:any[]){ // mixin decorator
    return function(target){
        mixins.forEach((mixin) => {
            add every function from mixing to target prototype, 
            if functions with same name does not exists there,
            so we are able to do calls to as example different render() functions   

            Will show it in OpenableItem        
        });
    }
}

function element = function(){
    return function(target){
        target.prototype.element = function(){
            return this.$el;
        }
    }
}
--------------------------------------------------------------------------------------
@element // every item will have this function as Root as Openable
class BaseItem{
    y() => number; // we need to get y position of every item
}
OpenableMixin{
    render() => render arrow only
    open(){} => change arrow position and cause menu to fire change event
    close(){} => change arrow position and cause menu to fire change event
}
class ItemsMixin extends OpenableMixing{// for now if item have childs it must be openable, 
                    // but Responsive has only tasks and must be openable too
    addItem(item: BaseItem) // need to add generics
    removeItem(item: BaseItem)  
}
--------------------------------------------------------------------------------------
@Mixin([ItemsMixin, ActivitiesMixin]) // it can have items and activities
class OpenableItem extends BaseItem implement ItemsMixin, ActivitiesMixin { // as in typescript docs
    render(){
        // call rendering from BaseItem class
        super.render();
        // call rendering from OpenableMixing
        OpenableMixin.prototype.render.call(this);
        // do some separate rendering for OpenableItem only
        this.$el.append('line');
    }   
}

@Mixin([ItemsMixin]) // it can have items
class RootItem extends BaseItem implement ItemsMixin{ // and subitems functionality is only for Root class
    subitems: Array<BaseItem> // need to add generics to be able to put here different item types
}
--------------------------------------------------------------------------------------
@element
class Menu{
    items: Array<Item>
}

@element
class Timeline{
    menu: Menu
    listAllelement() => {
        console.log(this.element());
        console.log(this.menu.element());
        this.menu.items.forEach((item) => {
            console.log(item.element());
            if(item.hasChilds()){  // really it must be (item instanceof RootItem || item instanceof OpenableItem)
                item.items.forEach((subitem) => { // really we need some recursion here
                    console.log(subitem.element());
                })
            }
        })
    }
}

In reality it is rare situation when you need to implement multiple inheritance, and it is much rarely when you can have such an issue in javascript. But every item can have different functionality depending on needs.

实际上,需要实现多重继承的情况很少见,而在 javascript 中遇到此类问题的情况也很少见。但是每个项目都可以根据需要具有不同的功能。

Just imagine that there can be different items which can have number of mixins. Is it wise to put everything into base ? And what is your approach to this issue ?

想象一下,可以有不同的项目可以有多个混合。将所有内容都放入 base 是否明智?你对这个问题的态度是什么?

回答by Alex

Currently, TypeScript does not have any special syntax to express multiple inheritance or mixins, but the official workaround can be found here.

目前,TypeScript 没有任何特殊的语法来表达多重继承或混合,但可以在这里找到官方的解决方法。

That strategy is basically that you let your main class implementthe classes that you want, write simple dummy implementation for their interfaces, and then have a special function that reads your classes and overwrites the properties in your main class.

这个策略基本上是让你的主类实现你想要的类,为它们的接口编写简单的虚拟实现,然后有一个特殊的函数来读取你的类并覆盖你的主类中的属性。

There are some suggestions to make TypeScript better at mixins/traits, eg. #2919and #311.

有一些建议可以让 TypeScript 在 mixins/traits 方面做得更好,例如。#2919#311

回答by Simon Epskamp

@kjetil-klaussen is correct, typescript 2.2 added support for the ECMAscript 2017 mixin pattern

@kjetil-klaussen 是正确的,typescript 2.2 添加了对ECMAscript 2017 混合模式的支持

Here is a full code sample:

这是一个完整的代码示例:

// http://justinfagnani.com/2015/12/21/real-mixins-with-javascript-classes/
// https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#support-for-mix-in-classes

type Constructor<T> = new (...args: any[]) => T;

class S {
  foo() {
    console.log('foo from S');
  }
}

// Here the possible SuperClass is set to {} (Object)
function Mixin1<T extends Constructor<{}>>(SuperClass: T) {
  return class extends SuperClass {
    foo() {
      console.log('foo from Mixin1');
      if (super.foo) super.foo();
    }
  };
}

// Here the possible SuperClass (S) is specified
function Mixin2<T extends Constructor<S>>(SuperClass: T) {
  return class extends SuperClass {
    foo() {
      console.log('foo from Mixin2');
      super.foo();
    }
  };
}

class C extends Mixin1(Mixin2(S)) {
  foo() {
    console.log('foo from C');
    super.foo();
  }
}

new C().foo();

This outputs:

这输出:

foo from C
foo from Mixin1
foo from Mixin2
foo from S

回答by Kjetil Klaussen

Typescript 2.2 added support for mix-ins.

Typescript 2.2 添加了对 mix-ins 的支持