TypeScript - สืบทอดคอมโพเนนต์สองตัวใน Angular โดยมีคอนสตรัคเตอร์ต่างกัน
นี่ค่อนข้างคล้ายกับการขยายคลาส 2 คลาสใน TypeScript แต่แม้ว่าฉันจะสามารถทำได้ใน TypeScript ฉันก็ไม่สามารถหาวิธีที่ถูกต้องใน Angular ได้
ฉันมีแอป Angular 7 ที่มีคอมโพเนนต์ 1 ตัว บริการ 1 ตัว และคลาสทั่วไป 1 คลาส
ตรงแบบนี้ Stackblitz
ฉันต้องการสร้างคอมโพเนนต์ที่สืบทอดมาจากคลาสของฉัน และคอมโพเนนต์อื่นของฉัน
นี่คือชั้นเรียนของฉัน =>
export class MyClass1<T,O> {
propertyClass1 = "MyClass1"
constructor() {
}
init(value:string){
this.propertyClass1 = value;
}
sayHelloClass(value:string){console.log('class say'+ value)}
}
นี่คือคอมโพเนนต์ของฉัน =>
export class MyCom1Component implements OnInit {
propertyComp1 = "MyCom1"
constructor(private service1:Service1Service) {
this.propertyComp1 = service1.getProp();
}
ngOnInit() {
}
sayHelloComponent(value:string){console.log('component say'+ value)}
}
ฉันอยากให้ลูกของฉันขยายบูธ เพื่อที่ฉันจะได้ทำ
ngOnInit() {
this.sayHelloClass(this.propertyClass1); // class say MyClass1
this.init("hoohoho");
this.sayHelloClass(this.propertyClass1); // class say hoohoho
this.sayHelloComponent(this.propertyComp1); // component say MyCom1
}
สิ่งที่ฉันลองทำคือสิ่งนี้ =>
const addMyClassOneInheritance = <T extends new(...args: any[]) => any>(MyCom1Component: T) => {
return class extends MyCom1Component {
constructor(...args: any[]) {
super(...args);
}
};
};
const MyMergedClass = addMyClassOneInheritance(MyClass1);
export class ChildComponent extends MyMergedClass<string,number> {
ngOnInit(){
this.sayHelloClass(this.propertyClass1); // compile ok, execute give a value
this.sayHelloComponent(this.propertyComp1); // compile ok, execute "can't find sayHelloComponent
}
}
ตัวคอมไพเลอร์ไม่ให้ข้อผิดพลาด แต่เมธอดของคอมโพเนนต์ของฉันไม่ได้ถูกสืบทอด
คำตอบ #1
ฉันขอแนะนำวิธีการที่แตกต่าง ทำให้คลาสสามารถใช้งานกับ DI ได้โดยการระบุด้วย @Injectable
จากนั้นขยายคอมโพเนนต์พ่อแม่ของคุณตามปกติ: ChildComponent extend MyCom1Component และฉีด MyClass1 ของคุณโดยใช้ตัวสร้างของ ChildComponent สุดท้ายเรียกตัวสร้างของพ่อแม่ด้วยอินสแตนซ์ของคลาสที่คุณเพิ่งฉีดเข้าไป
constructor(public myclass1: MyClass1) {
super(myclass1);
}
คำตอบ #2
Angular ไม่อนุญาตให้ การสืบทอดหลายชั้น คุณสามารถ ขยายได้เพียงคลาสเดียว ใน Angular แม้ว่าคุณสามารถ ใช้งานหลายอินเทอร์เฟซ แต่มีวิธีที่คุณสามารถทำการสืบทอดหลายชั้น (เฉพาะตัวอย่างเช่น say) โดยใช้ TypeScript Mixins
ข้อเสียเพียงอย่างเดียวของ mixins คือคุณจะต้อง กำหนดวิธีการทั้งหมดของคลาสฐานที่ใช้ในคลาสลูก [หมายเหตุ - นี่ไม่ใช่การสืบทอดจริง โดยพื้นฐานแล้ว คุณกำลังเพิ่มคุณสมบัติทั้งหมดของคลาสฐานไปยังคลาสลูก]
นอกจากนี้ คุณจะต้อง ประกาศ เมธอด mixin ที่ใดที่หนึ่งในโค้ดของคุณซึ่งจะทำงานหนักทั้งหมด (โดยปกติควรอยู่ที่ app.module เพื่อให้เข้าถึงได้ทั่วทั้งแอป)
ด้านล่างนี้เป็นวิธี mixin:
function applyMixins(derivedCtor: any, baseCtors: any[]) {
baseCtors.forEach(baseCtor => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
if (name !== 'constructor') {
derivedCtor.prototype[name] = baseCtor.prototype[name];
}
});
});
}
เอกสารอ้างอิง - https://www.stevefenton.co.uk/2014/02/TypeScript-Mixins-Part-One/
โปรดดูตัวอย่างโค้ดสำหรับ ChildComponent ของคุณ ฉันได้เพิ่มวิธี mixin ใน ChildComponent ของคุณเองแล้ว คุณสามารถวางมันที่ใดก็ได้ในโค้ดของคุณ
export class ChildComponent {
propertyClass1: string;
propertyComp1:string;
sayHelloClass: (value) => void;
init: (value) => void;
sayHelloComponent: (value) => void;
constructor(private service: Service1Service) {
// super()
}
ngOnInit() {
this.applyMixins(ChildComponent, [MyCom1Component,MyClass1]);
this.sayHelloClass(this.propertyClass1);
this.init("hoohoho");
this.sayHelloClass(this.propertyClass1);
this.sayHelloComponent(this.propertyComp1);
}
applyMixins(derivedCtor: any, baseCtors: any[]) {
baseCtors.forEach(baseCtor => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
if (name !== 'constructor') {
derivedCtor.prototype[name] = baseCtor.prototype[name];
}
});
});
}
}
