angular - ความแตกต่างระหว่างอินเตอร์เฟสและคลาสใน Typescript
ความแตกต่างระหว่าง Interfaces และ Classes ใน Typescript คืออะไร? ฉันควรใช้ Class เมื่อไหร่? ฉันควรใช้ Interfaces เมื่อไหร่? ข้อดีของพวกมันมีอะไรบ้าง?
ฉันจำเป็นต้องสร้างประเภทบางอย่างสำหรับคำขอ http ไปยังเซิร์ฟเวอร์แบ็กเอนด์ของฉัน (กำลังทำด้วย Angular 2) เช่น : },
"fields": {
"project": {
"id": "10000"
},
"summary": "something's wrong",
"issuetype": {
"id": "10000"
},
"assignee": { // not neccesary required
"name": "homer"
},
"reporter": {
"name": "smithers"
},
"priority": { // not neccesary required
"id": "20000"
}
}
ฉันควรใช้สิ่งใดในการสร้างโมเดลเหล่านี้? ขอบคุณ!
คำตอบ #1
2019: อัปเดตเกี่ยวกับความแตกต่างและการใช้งาน
ก่อนอื่น มีความแตกต่างที่ชัดเจน: ไวยากรณ์ นี่เป็นความแตกต่างที่ง่าย แต่จำเป็นต้องเข้าใจ: คุณสมบัติของอินเตอร์เฟซสามารถจบด้วยเครื่องหมายจุลภาคหรือเซมิโคลอน แต่คุณสมบัติของคลาสสามารถจบได้เพียงเซมิโคลอนเท่านั้น ตอนนี้สิ่งที่น่าสนใจ ส่วนที่เกี่ยวกับเมื่อใดควรใช้และไม่ควรใช้อาจเป็นเรื่องส่วนตัว - นี่คือแนวทางที่ฉันให้กับทีมของฉัน แต่ก็เป็นไปได้ว่าทีมอื่นอาจมีแนวทางอื่นด้วยเหตุผลที่ถูกต้อง ยินดีแสดงความคิดเห็นหากทีมของคุณทำต่างไป ฉันอยากเรียนรู้ว่าทำไม
อินเทอร์เฟซ: อนุญาตให้กำหนดประเภทที่จะใช้ในระหว่างการออกแบบและเวลาคอมไพล์เพื่อให้มีการพิมพ์ชนิดที่เข้มงวด สามารถ "นำไปใช้งาน" หรือ "ขยาย" ได้ แต่ไม่สามารถสร้างอินสแตนซ์ได้ (คุณไม่สามารถ new มัน) อินเทอร์เฟซจะถูกลบเมื่อทำการทรานสไพล์ลงเป็น JS ดังนั้นจะไม่กินพื้นที่ แต่ก็ไม่สามารถตรวจสอบชนิดในเวลารันไทม์ได้ ดังนั้นคุณไม่สามารถตรวจสอบว่าตัวแปรใด ๆ นำไปใช้งานประเภทเฉพาะในเวลารันไทม์ได้ (เช่น foo instanceof bar) ยกเว้นการตรวจสอบคุณสมบัติที่มันมี: การตรวจสอบชนิดอินเทอร์เฟซด้วย Typescript.
เวลาที่ควรใช้ interfaces: ใช้เมื่อคุณจำเป็นต้องสร้างสัญญาของคุณสมบัติและฟังก์ชันสำหรับอ็อบเจ็กต์ที่จะถูกใช้มากกว่าหนึ่งที่ในโค้ดของคุณ โดยเฉพาะมากกว่าหนึ่งไฟล์หรือฟังก์ชัน นอกจากนี้ ใช้เมื่อคุณต้องการให้อ็อบเจ็กต์อื่นเริ่มต้นด้วยชุดคุณสมบัติพื้นฐานนี้ เช่น การมี Vehicle interface ที่หลายคลาสนำไปใช้เป็นประเภทยานพาหนะเฉพาะ เช่น Car, Truck, Boat (เช่น class Car implements Vehicle)
เมื่อไม่ควรใช้ interfaces: เมื่อคุณต้องการมีค่าตั้งต้น, การใช้งาน, ตัวสร้าง, หรือฟังก์ชัน (ไม่ใช่เพียงแค่ลายเซ็น)
คลาส: ยังสามารถใช้สำหรับกำหนดชนิดที่จะใช้ในระหว่างการออกแบบและการคอมไพล์เพื่อให้มีการพิมพ์แบบเข้มงวด และ นอกจากนี้ ยังสามารถใช้ในระหว่างรันไทม์ได้ ซึ่งหมายความว่าโค้ดจะไม่ถูกคอมไพล์ออกไป ดังนั้นจะใช้พื้นที่ หนึ่งในความแตกต่างสำคัญที่ @Sakuto กล่าวถึง แต่ก็มีผลกระทบมากกว่าพื้นที่เพียงอย่างเดียว นั่นหมายความว่าคลาสสามารถตรวจสอบชนิดได้ รักษาความเข้าใจเกี่ยวกับ "พวกเขาคือใคร" แม้ในโค้ด JS ที่ถูกแปลงแล้ว ความแตกต่างเพิ่มเติม ได้แก่: คลาสสามารถถูกสร้างอินสแตนซ์โดยใช้ new และสามารถขยายได้ แต่ไม่สามารถนำไปใช้ได้ (implemented) คลาสสามารถมีคอนสตรัคเตอร์และโค้ดฟังก์ชันจริงพร้อมกับค่าเริ่มต้น
เมื่อใดควรใช้คลาส: เมื่อคุณต้องการสร้างออบเจ็กต์ที่มีโค้ดฟังก์ชันจริงอยู่ในนั้น มีคอนสตรัคเตอร์สำหรับการเริ่มต้นค่า และ/หรือคุณต้องการสร้างอินสแตนซ์ของมันด้วย new นอกจากนี้ สำหรับออบเจ็กต์ข้อมูลง่ายๆ คุณสามารถใช้คลาสในการตั้งค่าค่าดีฟอลต์ อีกครั้งที่คุณอาจต้องการใช้คลาสคือเมื่อคุณกำลังทำการตรวจสอบชนิดข้อมูล แม้ว่าจะมีวิธีแก้ไขสำหรับอินเทอร์เฟซหากจำเป็น (ดูส่วนอินเทอร์เฟซ OS ลิงก์)
เมื่อไม่ควรใช้คลาส: เมื่อคุณมีอินเทอร์เฟซข้อมูลที่เรียบง่าย ไม่จำเป็นต้องสร้างอินสแตนซ์เมื่อคุณต้องการให้มันถูกใช้งานโดยวัตถุอื่น ๆ เมื่อคุณต้องการเพียงแค่วางอินเทอร์เฟซบนวัตถุที่มีอยู่แล้ว (คิดถึงไฟล์การกำหนดชนิด) หรือเมื่อพื้นที่ที่มันจะใช้มากเกินไปหรือไม่จำเป็น เป็นข้อสังเกตเพิ่มเติม หากคุณดูในไฟล์ .d.ts คุณจะสังเกตได้ว่าพวกมันใช้เฉพาะอินเทอร์เฟซและประเภทเท่านั้น ดังนั้นสิ่งนี้จะถูกลบออกอย่างสมบูรณ์เมื่อถูกแปลงเป็น JavaScript.
บันทึกสุดท้าย ยังมีตัวเลือกอื่นอีกสองอย่างนอกจากคลาสและอินเทอร์เฟซ ตัวเลือกแรกคือสิ่งที่เรียกว่า "type" ซึ่งค่อนข้างคล้ายกับอินเทอร์เฟซ แต่ลองดูโพสต์ SO นี้ โดยเฉพาะคำตอบอัปเดตปี 2019: Interfaces vs Types in TypeScript ตัวเลือกสุดท้ายคือการใช้สไตล์การเขียนโปรแกรมเชิงฟังก์ชัน (ไม่ใช่ OOP) กับ TS
สำหรับเรื่องราวทั้งหมดพร้อมตัวอย่างเยี่ยมชม PassionForDev.com และสำหรับการอ่านเพิ่มเติมเกี่ยวกับคลาสเทียบกับการสืบทอดพร้อมตัวอย่างเยี่ยมชม https://jameshenry.blog/typescript-classes-vs-interfaces/
คำตอบ #2
ตามคู่มือสไตล์ของ Angular 2 แนะนำให้ใช้ Class แทน Interface สำหรับการกำหนดประเภท ความแตกต่างหลักคือ class จะคงอยู่เมื่อคอมไพล์ ในขณะที่ Interface จะถูกลบออกทั้งหมดเนื่องจากไม่ได้ใช้งานใด ๆ
เพียงแค่คงความสม่ำเสมอตลอดทั้งโครงการ และควรเลือกใช้แนวทาง styleguide กับ class ใครจะรู้ บางทีวันหนึ่งคุณอาจจำเป็นต้องเพิ่ม method ให้กับ models ของคุณ
ตรวจสอบคำตอบด้านล่างสำหรับรายละเอียดเพิ่มเติม: https://stackoverflow.com/a/55505227/5463904
คำตอบ #3
คลาสคือการสร้างวัตถุ และอินเทอร์เฟซช่วยให้คุณรู้ว่าวัตถุเหล่านี้ควรมีอะไรบ้าง
คลาสเหมือนกับพิมพ์เขียว/แม่แบบที่ใช้สร้างออบเจ็กต์ได้ อินเทอร์เฟซเหมือนกับสัญญาที่คลาสต้องตกลงเพื่อใช้อินเทอร์เฟซนั้นหรือกำหนดว่าสิ่งใดควรมีในพิมพ์เขียวนั้น
คลาสง่ายๆ:
class Car {
engine: string; // 'var' is not used;
constructor(engine: string) { // This is how we create constructor
this.engine = engine;
}
display(): void { // 'function' keyword is not used here.
console.log(`Engine is ${this.engine}`); // just a log.
}
}
var objCar = new Car('V8'); // creates new onject
objCar.display(); // output: Engine is V8
console.log(objCar.engine); // output: V8 (accessing member here)
อินเทอร์เฟซที่เรียบง่าย:
interface IPerson { // This is how we create an interface.
firstName: string, // use commas to separate.
lastName: string, // In classes we use semi-colon to separate.
displayDetails: (number) => string
}
// We are going to store 'interface object' in a variable.
// i.e. we are implementing interface with variable(not class!!)
var customer: IPerson = {
firstName: 'jose jithin', // 'implements' variables
lastName: 'stanly',
// Now method implementation.
// Note: the syntax of 'displayDetails' maybe a bit confusing (given below)
// as two colons are used.
// It specifies a return type(string) here for this method.
displayDetails: (rank): string => { return `This person has rank ${rank}. ` }
// It can be rewritten as following too.
displayDetails: (rank) => { return `This person has rank ${rank}. ` };
// i.e. return type need not be specified, just like a normal method definition syntax.
}
console.log(customer.firstName); // output: jose jithin
console.log(customer.lastName); // output: stanly
console.log(customer.displayDetails(1)); // output: This person has rank
ฉันได้อธิบายรายละเอียดเกี่ยวกับคลาสและอินเทอร์เฟซในบทความของฉัน ซึ่งอาจช่วยให้คุณเข้าใจได้
