Apa perbedaan antara 'extends' dan 'implements' di TypeScript

Jawaban:

153

Versi pendek

  • extends cara:

Kelas baru adalah anak-anak . Itu mendapat manfaat datang dengan warisan. Ia memiliki semua properti, metode sebagai induknya. Itu dapat menimpa beberapa di antaranya dan menerapkan yang baru, tetapi hal-hal induk sudah disertakan.

  • implements cara:

Kelas baru bisa diperlakukan sebagai "bentuk" yang sama , meski bukan anak-anak . Itu bisa diteruskan ke metode apa pun yang Persondiperlukan, terlepas dari memiliki induk yang berbeda dariPerson

Lebih ...

Dalam OOP (bahasa seperti C #, Java) kami akan menggunakan

extendsuntuk mendapatkan keuntungan dari warisan (lihat wiki ). Kutipan kecil:

... Pewarisan di sebagian besar bahasa berorientasi objek berbasis kelas adalah mekanisme di mana satu objek memperoleh semua properti dan perilaku objek induk. Pewarisan memungkinkan pemrogram untuk: membuat kelas yang dibangun di atas kelas yang ada ...

implementsakan lebih untuk polimorfisme (lihat wiki ). Kutipan kecil:

... polimorfisme adalah penyediaan antarmuka tunggal untuk entitas dari berbagai jenis ...

Jadi, kita dapat memiliki pohon warisan yang sangat berbeda dari kita class Man.

class Man extends Human ...

tetapi jika kami juga menyatakan bahwa kami dapat berpura-pura menjadi tipe yang berbeda - Person:

class Man extends Human 
          implements Person ...

.. kemudian kita bisa menggunakannya di mana saja, di mana Persondiperlukan. Kami hanya harus memenuhi Persons's "interface" (yaitu menerapkan semua barang publiknya) .

implementkelas lain? Itu hal yang sangat keren

Wajah Javascript yang bagus (salah satu manfaat) adalah dukungan bawaan dari pengetikan Duck ( lihat wiki ). Kutipan kecil:

"Jika dia berjalan seperti bebek dan dia dukun seperti bebek, maka dia pasti bebek."

Jadi, dalam Javascript, jika dua objek yang berbeda ... akan memiliki satu metode yang serupa (misalnya render()) mereka dapat diteruskan ke fungsi yang mengharapkannya:

function(engine){
  engine.render() // any type implementing render() can be passed
}

Untuk tidak kehilangan itu - kita bisa di Typecript melakukan hal yang sama - dengan lebih banyak dukungan yang diketik. Dan disitulah

class implements class

memiliki perannya sendiri, yang masuk akal

Dalam bahasa OOP sebagai C#... tidak ada cara untuk melakukan itu ...

Dokumentasi juga akan membantu di sini:

Antarmuka Memperluas Kelas

Ketika tipe antarmuka memperluas tipe kelas, itu mewarisi anggota kelas tetapi tidak implementasinya. Seolah-olah antarmuka telah mendeklarasikan semua anggota kelas tanpa menyediakan implementasi. Antarmuka bahkan mewarisi anggota pribadi dan terlindungi dari kelas dasar. Ini berarti bahwa ketika Anda membuat antarmuka yang memperluas kelas dengan anggota privat atau dilindungi, jenis antarmuka itu hanya dapat diterapkan oleh kelas itu atau subkelasnya.

Ini berguna ketika Anda memiliki hierarki pewarisan yang besar, tetapi ingin menentukan bahwa kode Anda hanya berfungsi dengan subclass yang memiliki properti tertentu. Subclass tidak harus terkait selain mewarisi dari kelas dasar. Sebagai contoh:

class Control {
    private state: any;
}

interface SelectableControl extends Control {
    select(): void;
}

class Button extends Control implements SelectableControl {
    select() { }
}

class TextBox extends Control {
    select() { }
}

// Error: Property 'state' is missing in type 'Image'.
class Image implements SelectableControl {
    private state: any;
    select() { }
}

class Location {

}

Jadi, sementara

  • extends artinya - itu mendapat semua dari induknya
  • implementsdalam hal ini hampir seperti mengimplementasikan interface. Objek anak dapat berpura-pura bahwa itu adalah orang tua ... tetapi tidak mendapatkan implementasi apa pun
Radim Köhler
sumber
ketika Anda mengatakan " extends-itu mendapat semua dari induknya", apakah itu berlaku untuk anggota pribadi? Misalnya class Person {private name: string} class man extends Person{gender: string;}apakah manmemiliki nama properti?
davejoem
Pribadi juga ada di sana. Hanya tidak dapat diakses oleh TS. Buat mereka terlindungi dan Anda dapat menggunakannya. Dalam kasus "mengimplementasikan" hanya bagian publik yang masuk akal. Semoga membantu sedikit
Radim Köhler
Jawaban yang sangat bagus. Hanya tidak yakin dengan komentar Anda untuk "pribadi ada tetapi tidak dapat diakses oleh TS". Maksud Anda, properti pribadi disalin dalam objek anak yang baru dibuat itu? Dan dalam kasus implementasi, hanya properti publik yang disalin?
kushalvm
Juga, saya mendapatkan satu poin lagi. Jika ini definisi extends. Maka tolong jika Anda bisa menjelaskan stackoverflow.com/questions/60390454/…
kushalvm
98

Dalam skrip ketikan (dan beberapa bahasa OO lainnya) Anda memiliki kelas dan antarmuka.

Sebuah antarmuka tidak memiliki implementasi, itu hanya sebuah "kontrak" dari anggota / metode yang dimiliki tipe ini.
Sebagai contoh:

interface Point {
    x: number;
    y: number;
    distance(other: Point): number;
}

Contoh yang mengimplementasikan Pointantarmuka ini harus memiliki dua anggota dengan tipe nomor: xdan y, dan satu metode distanceyang menerima Pointcontoh lain dan mengembalikan a number.
Antarmuka tidak menerapkan semua itu.

Kelas adalah implementasinya:

class PointImplementation implements Point {
    public x: number;
    public y: number;

    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;
    }

    public distance(other: Point): number {
        return Math.sqrt(Math.pow(this.x - other.x, 2) + Math.pow(this.y - other.y, 2));
    }
}

( kode di taman bermain )

Dalam contoh Anda, Anda memperlakukan Personkelas Anda sekali sebagai kelas saat Anda memperluasnya dan sekali sebagai antarmuka saat Anda mengimplementasikannya.
Kode Anda:

class Person {
    name: string;
    age: number;
}
class Child  extends Person {}

class Man implements Person {}

Memiliki kesalahan kompilasi yang mengatakan:

Kelas 'Manusia' salah mengimplementasikan antarmuka 'Orang'.
Properti 'nama' tidak ada di tipe 'Man'.

Dan itu karena antarmuka kurang implementasi.
Jadi jika Anda implementadalah sebuah kelas maka Anda hanya mengambil "kontrak" tanpa implementasi, jadi Anda harus melakukan ini:

class NoErrorMan implements Person {
    name: string;
    age: number;
}

( kode di taman bermain )

Intinya adalah bahwa dalam banyak kasus Anda ingin ke extendkelas lain dan bukan ke kelas implementitu.

Nitzan Tomer
sumber
7
Jawaban ini lebih sederhana untuk dipahami.
Akshay Raut
6

Jawaban Hebat dari @ nitzan-tomer! Sangat membantu saya ... Saya sedikit memperpanjang demonya dengan:

IPoint interface;
Point implements IPoint;
Point3D extends Point;

Dan bagaimana mereka berperilaku dalam fungsi yang mengharapkan sebuah IPointtipe.

Jadi apa yang telah saya pelajari sejauh ini dan telah digunakan sebagai aturan umum: Jika Anda menggunakan kelas dan metode yang mengharapkan tipe generik, gunakan antarmuka sebagai tipe yang diharapkan. Dan pastikan orang tua atau kelas dasar menggunakan antarmuka itu. Dengan cara itu Anda dapat menggunakan semua subclass sejauh mereka mengimplementasikan antarmuka.

Berikut demo yang diperpanjang

andzep
sumber
Ini tidak memberikan jawaban atas pertanyaan tersebut. Untuk mengkritik atau meminta klarifikasi dari seorang penulis, tinggalkan komentar di bawah postingannya. - Dari Ulasan
aronisstav
1
@aronisstav Saya hanya memposting demo diperpanjang dari apa yang saya temukan jawaban bagus yang sudah membantu saya. Tapi mungkin orang lain akan menganggap pekerjaan yang saya lakukan untuk memperpanjang demo berguna. Itu saja. Komentar tidak benar-benar dimaksudkan untuk meletakkan blok kode, jadi itulah mengapa saya merasa lebih dapat dipahami dalam Posting-Jawaban. Jadi apa masalahnya?
andzep
Jawaban Anda (secara otomatis?) Ditandai karena panjang dan isinya, muncul dalam antrean tinjauan saya dan saya pantas untuk alasan yang disajikan dalam bendera. Kontribusi utamanya (menjelaskan bahwa Anda memperpanjang demo) akan lebih baik sebagai komentar. Dengan menambahkan paragraf mungkin memang lebih bermanfaat.
aronisstav
@andzep Contoh demo tambahan Anda sangat membantu.
namit
3
  1. Antarmuka memperluas antarmuka dengan bentuk
  2. Antarmuka memperluas kelas dengan bentuk
  3. Antarmuka implementasi kelas harus mengimplementasikan semua bidang yang disediakan oleh antarmuka
  4. Kelas mengimplementasikan kelas dengan bentuk
  5. Kelas memperluas kelas dengan semua bidang

extendsfokus pada mewarisi dan implementsfokus pada kendala apakah antarmuka atau kelas.

lei li
sumber
0

Memperluas implementasi VS

  • extends: Kelas anak (yang diperpanjang) akan mewarisi semua properti dan metode kelas diperpanjang
  • implements: Kelas yang menggunakan implementskata kunci perlu mengimplementasikan semua properti dan metode kelas yang ituimplements

Sederhananya:

  • extends: Di sini Anda mendapatkan semua metode / properti ini dari kelas induk sehingga Anda tidak perlu mengimplementasikannya sendiri
  • implements: Ini adalah kontrak yang harus diikuti oleh kelas. Kelas harus mengimplementasikan setidaknya metode / properti berikut

Contoh:

class Person {
  name: string;
  age: number;

  walk(): void {
    console.log('Walking (person Class)')
  }

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}
class child extends Person { }

// Man has to implements at least all the properties
// and methods of the Person class
class man implements Person {
  name: string;
  age: number

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  walk(): void {
    console.log('Walking (man class)')
  }

}

(new child('Mike', 12)).walk();
// logs: Walking(person Class)

(new man('Tom', 12)).walk();
// logs: Walking(man class)

Dalam contoh kita dapat mengamati bahwa kelas anak mewarisi segalanya dari Person sedangkan kelas man harus mengimplementasikan semuanya dari Person itu sendiri.

Jika kita menghapus sesuatu dari kelas man misalnya metode berjalan kita akan mendapatkan kesalahan waktu kompilasi berikut :

Kelas 'man' salah mengimplementasikan kelas 'Person'. Apakah Anda bermaksud memperluas 'Orang' dan mewarisi anggotanya sebagai subkelas? Properti 'berjalan' tidak ada dalam tipe 'man' tetapi diperlukan dalam tipe 'Person'. (2720)

Willem van der Veen
sumber