ค้นหาเว็บไซต์

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 

ฉันได้อธิบายรายละเอียดเกี่ยวกับคลาสและอินเทอร์เฟซในบทความของฉัน ซึ่งอาจช่วยให้คุณเข้าใจได้

บทความที่เกี่ยวข้อง