将Typescript装饰器作为mixin?

将Typescript装饰器作为mixin?,typescript,angular,Typescript,Angular,我正在用Angular2写一个大的应用程序。我有一个基类可以这样做: export abstract class ReactiveComponent implements OnInit, OnDestroy, AfterViewInit { abstract ngOnInit(): void; protected _subscriptions: Rx.Subscription[] = []; private __viewInit = new Rx.Subject<v

我正在用Angular2写一个大的应用程序。我有一个基类可以这样做:

export abstract class ReactiveComponent implements OnInit, OnDestroy, AfterViewInit {
    abstract ngOnInit(): void;
    protected _subscriptions: Rx.Subscription[] = [];
    private __viewInit = new Rx.Subject<void>();
    protected _viewInit: Rx.Observable<void> = this.__viewInit;
    ngOnDestroy() {
        if (this._subscriptions)
            this._subscriptions.forEach(s => s.unsubscribe());
    }
    ngAfterViewInit() {
        this.__viewInit.complete();

    }
}
导出抽象类ReactiveComponent实现OnInit、OnDestroy和AfterViewInit{
抽象ngOnInit():void;
受保护的订阅:Rx.Subscription[]=[];
private _viewInit=new Rx.Subject();
受保护的viewInit:Rx.Observable=this.viewInit;
恩贡德斯特罗(){
如果(此订阅)
此.u subscriptions.forEach(s=>s.unsubscribe());
}
ngAfterViewInit(){
这是.u viewInit.complete();
}
}
但是我的一些类需要有其他的基类,我遇到了经典的mixin/继承砖墙

所以我想把它变成一个装饰器,因为Angular2不关心这些方法来自哪里,我可以很容易地做一个
constructor.prototype.ngondestory=…

对吗?

这给我留下了两个问题:

  • 我有没有办法让受保护的成员“出现”在装饰类中,这样我就可以用Typescript编写
    这个
  • 如果我想添加一个
    @ContentChildren(…)something通过mixin的属性?如何在
    constructor.prototype.something
    上动态定义装饰器?我对“特质”的理解是错误的吗
  • (1) 不,您可能无法同时享受使用mixin和拥有受保护的成员/方法的乐趣。
    虽然mixin是实际的类,但可以将它们作为接口继承:

    class MixinA {
        public a(): void { console.log("A"); }
    }
    
    class MixinB {
        public b(): void { console.log("B"); }
    }
    
    class MyClass implements MixinA, MixinB {
        public a: () => void;
        public b: () => void;
    }
    
    applyMixins(MyClass, [MixinA, MixinB]);
    
    其中关键字为
    实现

    作为一般的OO原则,接口是公共契约,它们不处理实际的实现,而实际的实现是受保护的功能领域

    (2) 如果我理解正确,当你说
    “动态定义装饰器”
    时,那么是的,这与官方文档中的示例类似,因此你应该能够执行类似(未测试的):

    const numbersmatakey=Symbol(“数字”);
    类型生产者=()=>数量;
    减速器类型=(上一个:编号,当前:编号)=>编号;
    函数编号(…道具:数组){
    返回Reflect.metadata(numberMetadataKey,props);
    }
    函数getNumbers(目标:MyClass,propertyKey:string){
    让arr:Array=Reflect.getMetadata(numbersMetadataKey、target、propertyKey);
    返回arr.map(item=>typeof item===“number”?item:item());
    }
    函数编号工厂(最小:编号=0,最大:编号=100):编号{
    返回Math.random()*(max-min)+min;
    }
    类MyClass{
    @数字(numberFactory(),numberFactory.bind(null,50200))
    私人减速机:减速机;
    建造师(减速器:减速器){
    这个减速机=减速机;
    }
    reduce():数字{
    let numbers:number[]=getNumbers(这是“减速机”);
    返回数字.reduce(这个.reducer);
    }
    }
    新建MyClass((上一个,当前)=>上一个+当前).reduce();
    新建MyClass((上一个,当前)=>上一个*当前).reduce();
    

    我只想补充一点,有时候多重继承是必需的,而且是不可避免的,如果支持的话(这里是用mixin实现的),但在其他时候,对多重继承的需要只是指向一个不充分的设计。

    是的,我实际上不想要多重继承,我想要的是“Traits”或“AOP”或者不管我们称之为什么,这些daysmixin都是特性,这就是在typescript中实现多重继承的方式。我的观点是,虽然有时这是最好的方法,但在其他情况下,您可以更改设计并使用普通继承,这在大多数情况下更容易。在任何情况下,我都展示了如何使用mixin来完成您要完成的任务。好吧,我将尝试找到一种不需要那些受保护成员的方法。。。我其余的需求都能通过混合得到充分满足。至于(2),一旦我完全理解了你的例子的作用,我可能会有更多的问题
    const numbersMetadataKey = Symbol("numbers");
    type Producer = () => number;
    type Reducer = (previous: number, current: number) => number;
    
    function numbers(...props: Array<number | Producer>) {
        return Reflect.metadata(numbersMetadataKey, props);
    }
    
    function getNumbers(target: MyClass, propertyKey: string) {
        let arr: Array<number | Producer> = Reflect.getMetadata(numbersMetadataKey, target, propertyKey);
        return arr.map(item => typeof item === "number" ? item : item());
    }
    
    function numberFactory(min: number = 0, max: number = 100): number {
        return Math.random() * (max - min) + min;
    }
    
    class MyClass {
        @numbers(numberFactory(), numberFactory.bind(null, 50, 200))
        private reducer: Reducer;
    
        constructor(reducer: Reducer) {
            this.reducer = reducer;
        }
    
        reduce(): number {
            let numbers: number[] = getNumbers(this, "reducer");
            return numbers.reduce(this.reducer);
        }
    }
    
    new MyClass((previous, current) => previous + current).reduce();
    new MyClass((previous, current) => previous * current).reduce();