Antarmuka atau Kelas Abstrak: yang mana yang akan digunakan?

327

Tolong jelaskan kapan saya harus menggunakan PHP interfacedan kapan saya harus menggunakan abstract class?

Bagaimana saya bisa mengubahnya abstract classmenjadi interface?

Darryl Hein
sumber

Jawaban:

458

Gunakan antarmuka saat Anda ingin memaksa pengembang yang bekerja di sistem Anda (termasuk Anda sendiri) untuk mengimplementasikan sejumlah metode pada kelas yang akan mereka bangun.

Gunakan kelas abstrak saat Anda ingin memaksa pengembang yang bekerja di sistem Anda (termasuk Anda sendiri) untuk mengimplementasikan sejumlah metode dan Anda ingin memberikan beberapa metode dasar yang akan membantu mereka mengembangkan kelas anak mereka.

Hal lain yang perlu diingat adalah kelas klien hanya dapat memperluas satu kelas abstrak, sedangkan mereka dapat mengimplementasikan banyak antarmuka. Jadi, jika Anda mendefinisikan kontrak perilaku Anda di kelas abstrak, itu berarti setiap kelas anak hanya dapat memenuhi satu kontrak. Terkadang ini hal yang baik, ketika Anda ingin memaksa pengguna-pemrogram Anda di sepanjang jalur tertentu. Lain kali itu akan buruk. Bayangkan jika antarmuka PHP yang Dapat Dihitung dan Iterator adalah kelas abstrak, bukan antarmuka.

Salah satu pendekatan yang umum ketika Anda tidak yakin ke mana harus pergi (seperti yang disebutkan oleh cletus di bawah ) adalah membuat antarmuka, dan kemudian minta kelas abstrak Anda mengimplementasikan antarmuka itu.

Alan Storm
sumber
12
Saya berusaha sepanjang hari untuk memahami penggunaan abstractdan interfacekelas, posting Anda membuat semuanya menjadi jelas. Terima kasih banyak Alan
afarazit
4
Keuntungan lain dari kelas abstrak adalah kemampuan untuk mendefinisikan metode yang dilindungi abstrak . Tidak selalu berguna, tetapi dapat berguna dalam beberapa arsitektur.
netcoder
Jadi dalam banyak kasus kita harus menggunakan kelas abstrak karena fleksibilitas - itu kesimpulan saya :)
ymakux
3
@volocuga: tidak harus, seperti yang Alan tunjukkan, hanya satu abstrak yang dapat diperpanjang. Saya pribadi tidak suka abstrak mengimplementasikan ide antarmuka karena memberikan kontribusi untuk kebingungan kode dan kurang langsung, IMO.
Awalan
171

Perbedaan antara an Abstract Classdan Interface:

Kelas Abstrak

Kelas abstrak dapat menyediakan beberapa fungsionalitas dan meninggalkan sisanya untuk kelas turunan .

  • Kelas turunan mungkin atau mungkin tidak mengesampingkan fungsi konkret yang didefinisikan dalam kelas dasar.

  • Kelas anak yang diperluas dari kelas abstrak harus secara logis terkait.

Antarmuka

Antarmuka tidak dapat berisi fungsionalitas apa pun . Ini hanya berisi definisi metode.

  • Kelas turunan HARUS memberikan kode untuk semua metode yang didefinisikan dalam antarmuka .

  • Kelas yang benar-benar berbeda dan tidak terkait dapat secara logis dikelompokkan bersama menggunakan antarmuka.

kn3l
sumber
1
Bisakah Anda memberikan contoh kehidupan nyata untuk menunjukkannya?
RN Kushwaha
1
Apa perbedaan antara abstract class X implements Ydan class X implements Y?
Webinan
3
@Webinan Dalam abstract class X implements YAnda menyatakan bahwa fungsionalitas massal X harus diimplementasikan dalam kelas turunan dan bahwa kedua kelas abstrak dan turunan harus berisi fungsi yang didefinisikan dalam Y, sementara class X implements Yhanya menyiratkan bahwa kelas X harus berisi fungsi yang didefinisikan dalam Y. Jika antarmuka Y tidak dimaksudkan untuk diimplementasikan oleh kelas lain selain XI akan benar-benar melewati mendefinisikan Y sebagai antarmuka dan hanya mengimplementasikan fungsi-fungsi dalam Y sebagai fungsi abstrak publik / terproteksi / privat untuk memastikan mereka diimplementasikan dalam kelas turunan.
Calle Bergström
1
Antarmuka tidak hanya dapat berisi definisi metode, mereka juga dapat berisi konstanta
Thielicious
Menyukai perbandingan Anda. Jadi ingin menambahkan sesuatu. Antarmuka dapat memiliki konstanta kelas di luar kotak sementara kelas abstrak tidak bisa.
Noman Ibrahim
128

Mengapa menggunakan kelas abstrak? Berikut ini adalah contoh sederhana. Katakanlah kita memiliki kode berikut:

<?php 

class Fruit {
    private $color;

    public function eat() {
        // chew
    }

    public function setColor($c) {
        $this->color = $c;
    }
}

class Apple extends Fruit {
    public function eat() {
        // chew until core
    }
}

class Orange extends Fruit {
    public function eat() {
        // peeling
        // chew
    }
}

Sekarang saya memberi Anda sebuah apel dan Anda memakannya. Bagaimana rasanya? Rasanya seperti apel.

<?php 
$apple = new Apple();
$apple->eat();

// Now I give you a fruit.
$fruit = new Fruit();
$fruit->eat();

Seperti apa rasanya? Yah, itu tidak masuk akal, jadi kamu seharusnya tidak bisa melakukan itu. Ini dicapai dengan membuat kelas Buah abstrak serta metode makan di dalamnya.

<?php 
abstract class Fruit {
    private $color;

    abstract public function eat(){}

    public function setColor($c) {
        $this->color = $c;
    }
}
?>

Kelas abstrak sama seperti antarmuka, tetapi Anda dapat mendefinisikan metode dalam kelas abstrak sedangkan di antarmuka semuanya abstrak. Kelas abstrak dapat memiliki metode kosong dan metode kerja / beton. Dalam antarmuka, fungsi yang didefinisikan tidak boleh memiliki tubuh. Di kelas abstrak, mereka bisa.

Contoh dunia nyata:

<?php 
abstract class person {

    public $LastName;
    public $FirstName;
    public $BirthDate;

    abstract protected function write_info();
}

final class employee extends person{

    public $EmployeeNumber;
    public $DateHired;

    public function write_info(){
        //sql codes here
        echo "Writing ". $this->LastName . "'s info to emloyee dbase table <br>";   
    }
}

final class student extends person{

    public $StudentNumber;
    public $CourseName;

    public function write_info(){
        //sql codes here
        echo "Writing ". $this->LastName . "'s info to student dbase table <br>";
    }
}

///----------
$personA = new employee;
$personB = new student;

$personA->FirstName="Joe";
$personA->LastName="Sbody";

$personB->FirstName="Ben";
$personB->LastName="Dover";

$personA->write_info();
// Writing Sbody's info to emloyee dbase table
$personB->write_info();
// Writing Dover's info to student dbase table 
Vineesh Kalarickal
sumber
2
Hai, jawaban ini mungkin mendapat downvotes karena cara diformat. Akan lebih baik jika itu bukan blok kode besar (empat spasi membuat sesuatu menjadi blok kode, lepaskan teks untuk mengeluarkannya dari blok), dan jika ini disalin-tempel dari suatu tempat (sepertinya begitu) akan sopan untuk memuji mereka.
Camilo Martin
9
Aku cinta kamu untuk contoh buah man! Sejak saya mulai belajar php, exmaples ini membuat saya jelas terima kasih banyak
Raheel
23
+1 What does that taste like? Well, it doesn't make much sense, so you shouldn't be able to do that.Sekarang saya tahu abstrak!
Webinan
Apa yang dilakukan finalkata kunci? Pos yang bagus, terima kasih.
Gus
1
@VineeshKalarickal Apa yang saya tidak mengerti dalam contoh Person adalah perbedaan antara: 1) menggunakan Person kelas abstrak (seperti pada contoh); 2) menulis Orang sebagai kelas standar dan membuat Karyawan dan Siswa mengganti metode write_info ().
Ferex
66

Praktik terbaik adalah menggunakan antarmuka untuk menentukan kontrak dan kelas abstrak sebagai hanya satu implementasi daripadanya. Kelas abstrak itu dapat mengisi banyak boilerplate sehingga Anda dapat membuat implementasi dengan hanya mengesampingkan apa yang Anda butuhkan atau inginkan tanpa memaksa Anda untuk menggunakan implementasi tertentu.

cletus
sumber
37

Hanya untuk melempar ini ke dalam campuran, tetapi seperti yang disebutkan Cletus menggunakan antarmuka bersama dengan kelas abstrak, saya sering menggunakan antarmuka untuk memperjelas pemikiran desain saya.

Misalnya:

<?php
class parser implements parserDecoratorPattern {
    //...
}

Dengan begitu, siapa pun yang membaca kode saya (dan siapa yang tahu apa itu Pola Penghias) akan langsung tahu a) bagaimana saya membuat parser dan b) dapat melihat metode apa yang digunakan untuk menerapkan pola dekorator.

Juga, dan saya mungkin berada di luar pangkalan di sini bukan menjadi programmer Java / C ++ / etc, tetapi tipe data dapat ikut bermain di sini. Objek Anda adalah tipe, dan ketika Anda menyebarkannya di sekitar tipe, hal-hal terprogram. Memindahkan item yang dapat dikontrak ke antarmuka hanya menentukan jenis metode yang dikembalikan, tetapi bukan tipe dasar dari kelas yang mengimplementasikannya.

Sudah terlambat dan saya tidak bisa memikirkan contoh kode-psudo yang lebih baik, tetapi begini:

<?php
interface TelevisionControls {};
class Remote implements TelevisionControls {};
class Spouse implements TelevisionControls {};
Spouse spouse = new Spouse();
Remote remote = new Remote();
isSameType = (bool)(remote == spouse)
Austen Hoogen
sumber
1
Contoh yang luar biasa! ;)
Joel Murphy
@ matt2000 Bukan seksis DAN bekerja untuk pernikahan sesama jenis sekarang juga. Suntingan yang bagus. :)
Austen Hoogen
4
Ini adalah contoh yang luar biasa! Namun, saya tidak berpikir Anda dapat membuat instantiate kelas abstrak melainkan kelas yang memanjang dari kelas abstrak
Arielle Nguyen
2
tidak akan membunuh untuk membuat kode sudo setidaknya terlihat seperti bahasa yang dimaksud. seseorang harus menaruh $ di sana.
Aku pernah bergulat dengan beruang.
2
Meskipun contohnya lucu, kami tidak dapat membuat instantiate kelas abstrak secara langsung, harap buat perubahan pada contoh tersebut sehingga orang mungkin tidak menganggapnya sebagai penggunaan yang valid dalam PHP.
saji89
16

Perbedaan utama adalah kelas abstrak dapat berisi implementasi standar sedangkan antarmuka tidak bisa.

Antarmuka adalah kontrak perilaku tanpa implementasi apa pun.

Mitch Wheat
sumber
16

Juga, hanya ingin menambahkan di sini bahwa hanya karena bahasa OO lainnya memiliki beberapa jenis antarmuka dan abstraksi juga tidak berarti mereka memiliki arti dan tujuan yang sama seperti di PHP. Penggunaan abstraksi / antarmuka sedikit berbeda sedangkan antarmuka dalam PHP sebenarnya tidak memiliki fungsi nyata. Mereka hanya digunakan untuk alasan semantik dan terkait skema. Intinya adalah memiliki proyek sebanyak fleksibel mungkin, diperluas dan aman untuk ekstensi di masa depan terlepas apakah pengembang di kemudian hari memiliki rencana penggunaan yang sama sekali berbeda atau tidak.

Jika bahasa Inggris Anda bukan asli, Anda dapat mencari Abstraksi dan Antarmuka apa sebenarnya. Dan mencari sinonim juga.

Dan ini mungkin membantu Anda sebagai metafora:

ANTARMUKA

Katakanlah, Anda membuat kue jenis baru dengan stroberi dan Anda membuat resep yang menggambarkan bahan dan langkah-langkahnya. Hanya Anda yang tahu mengapa rasanya begitu enak dan tamu Anda menyukainya. Kemudian Anda memutuskan untuk menerbitkan resep Anda sehingga orang lain dapat mencoba kue itu juga.

Intinya di sini adalah

- untuk memperbaikinya
- untuk berhati
-
hati - untuk mencegah hal-hal yang dapat memburuk (seperti terlalu banyak stroberi atau sesuatu) - untuk memudahkan orang-orang yang mencobanya
- untuk memberi tahu Anda berapa lama apa yang harus dilakukan (seperti stiring )
- untuk mengetahui hal-hal yang BISA Anda lakukan tetapi tidak HARUS melakukannya

Persis inilah yang menggambarkan antarmuka. Ini adalah panduan, satu set instruksi yang mengamati isi resep. Sama seperti jika Anda ingin membuat proyek dalam PHP dan Anda ingin memberikan kode pada GitHub atau dengan teman Anda atau apa pun. Antarmuka adalah apa yang dapat dilakukan orang dan apa yang seharusnya tidak Anda lakukan. Aturan yang menahannya - jika Anda tidak mematuhi satu, seluruh konstruk akan dilanggar.


ABSTRAKSI

Untuk melanjutkan metafora ini di sini ... bayangkan, Anda adalah tamu saat ini makan kue itu. Maka Anda mencoba kue itu menggunakan resep sekarang. Tetapi Anda ingin menambahkan bahan-bahan baru atau mengubah / melewatkan langkah-langkah yang dijelaskan dalam resep. Jadi apa yang terjadi selanjutnya? Rencanakan versi yang berbeda dari kue itu. Kali ini dengan blackberry, bukan strawberry, dan lebih banyak vanilla cream ... yummy.

Inilah yang dapat Anda pertimbangkan sebagai perpanjangan dari kue asli. Anda pada dasarnya melakukan abstraksi dengan membuat resep baru karena ini sedikit berbeda. Ini memiliki beberapa langkah baru dan bahan lainnya. Namun, versi black berry memiliki beberapa bagian yang Anda ambil dari aslinya - ini adalah langkah dasar yang harus dimiliki setiap jenis kue itu. Suka bahan-bahan seperti susu - Itulah yang dimiliki setiap kelas turunan.

Sekarang Anda ingin bertukar bahan dan langkah dan ini HARUS ditentukan dalam versi baru kue itu. Ini adalah metode abstrak yang harus didefinisikan untuk kue baru, karena harus ada buah di kue tapi yang mana? Jadi kamu ambil black black kali ini. Selesai

Begitulah, Anda telah memperpanjang kue, mengikuti antarmuka dan langkah-langkah abstrak dan bahan dari itu.

Sangat berbahaya
sumber
1
Ini adalah perbandingan favorit saya tentang apa pun yang terkait dengan PHP. Sangat masuk akal. Terima kasih!
cbloss793
13

Untuk menambahkan beberapa jawaban yang sudah sangat bagus:

  • Kelas abstrak memungkinkan Anda memberikan beberapa tingkat implementasi, antarmuka adalah templat murni. Antarmuka hanya dapat mendefinisikan fungsionalitas , tidak pernah dapat mengimplementasikannya.

  • Setiap kelas yang mengimplementasikan antarmuka berkomitmen untuk mengimplementasikan semua metode yang didefinisikannya atau harus dinyatakan abstrak.

  • Antarmuka dapat membantu mengelola fakta bahwa, seperti Java, PHP tidak mendukung banyak pewarisan. Kelas PHP hanya dapat memperpanjang satu induk. Namun, Anda dapat membuat janji kelas untuk mengimplementasikan sebanyak mungkin antarmuka yang Anda inginkan.

  • type: untuk setiap interface yang diimplementasikan, kelas mengambil tipe yang sesuai. Karena setiap kelas dapat mengimplementasikan antarmuka (atau lebih banyak antarmuka), antarmuka secara efektif menggabungkan tipe yang tidak terkait.

  • suatu kelas dapat memperluas superclass dan mengimplementasikan sejumlah antarmuka:

    class SubClass extends ParentClass implements Interface1, Interface2 {
        // ...
    }

Tolong jelaskan kapan saya harus menggunakan antarmuka dan kapan saya harus menggunakan kelas abstrak?

Gunakan antarmuka saat Anda hanya perlu menyediakan templat tanpa implementasi apa pun, dan Anda ingin memastikan setiap kelas yang mengimplementasikan antarmuka tersebut memiliki metode yang sama dengan kelas lain yang mengimplementasikannya (setidaknya).

Gunakan kelas abstrak saat Anda ingin membuat fondasi untuk objek lain (kelas yang dibangun sebagian). Kelas yang memperluas kelas abstrak Anda akan menggunakan beberapa properti atau metode yang didefinisikan / diimplementasikan:

<?php
// interface
class X implements Y { } // this is saying that "X" agrees to speak language "Y" with your code.

// abstract class
class X extends Y { } // this is saying that "X" is going to complete the partial class "Y".
?>

Bagaimana saya bisa mengubah kelas abstrak saya menjadi antarmuka?

Ini adalah contoh / contoh sederhana. Keluarkan detail implementasi apa pun. Misalnya, ubah kelas abstrak Anda dari:

abstract class ClassToBuildUpon {
    public function doSomething() {
          echo 'Did something.';
    }
}

untuk:

interface ClassToBuildUpon {
    public function doSomething();
}
bg17aw
sumber
12

Dari sudut pandang filosofis:

  • Kelas abstrak mewakili hubungan "adalah". Katakanlah saya punya buah, yah saya akan memiliki kelas abstrak Buah yang berbagi tanggung jawab dan perilaku umum.

  • Antarmuka mewakili hubungan "harus dilakukan". Sebuah antarmuka, menurut pendapat saya (yang merupakan pendapat dari seorang junior dev), harus dinamai dengan suatu tindakan, atau sesuatu yang dekat dengan suatu tindakan, (Maaf, tidak dapat menemukan kata, saya bukan penutur asli bahasa Inggris) katakanlah IEatable. Anda tahu itu bisa dimakan, tetapi Anda tidak tahu apa yang Anda makan.

Dari sudut pandang pengkodean:

  • Jika objek Anda memiliki kode duplikat, itu merupakan indikasi bahwa mereka memiliki perilaku umum, yang berarti Anda mungkin memerlukan kelas abstrak untuk menggunakan kembali kode, yang tidak dapat Anda lakukan dengan antarmuka.

  • Perbedaan lain adalah bahwa suatu objek dapat mengimplementasikan sebanyak mungkin antarmuka yang Anda butuhkan, tetapi Anda hanya dapat memiliki satu kelas abstrak karena "masalah intan" (lihat di sini untuk mengetahui mengapa! Http://en.wikipedia.org/wiki/ Multiple_inheritance # The_diamond_problem )

Saya mungkin lupa beberapa poin, tapi saya harap ini bisa menjelaskan beberapa hal.

PS: "adalah" / "harus dilakukan" dibawa oleh jawaban Vivek Vermani, saya tidak bermaksud mencuri jawabannya, hanya untuk menggunakan kembali istilah-istilah itu karena saya suka mereka!

IEatBagels
sumber
2
Kata yang Anda cari bisa dimakan, saya percaya.
Travis Weston
1
Sebenarnya, saya percaya ini adalah "Verb", "kata yang melakukan"
Grizly
7

Perbedaan teknis antara kelas abstrak dan antarmuka sudah tercantum dalam jawaban lain dengan tepat. Saya ingin menambahkan penjelasan untuk memilih antara kelas dan antarmuka saat menulis kode demi pemrograman berorientasi objek.

Kelas harus mewakili entitas sedangkan antarmuka harus mewakili perilaku.

Mari kita ambil contoh. Monitor komputer adalah entitas dan harus direpresentasikan sebagai kelas.

class Monitor{
    private int monitorNo;
}

Ini dirancang untuk memberikan antarmuka tampilan kepada Anda, sehingga fungsionalitas harus ditentukan oleh antarmuka.

interface Display{
    void display();
}

Ada banyak hal lain yang perlu dipertimbangkan seperti dijelaskan dalam jawaban lain, tetapi ini adalah hal paling mendasar yang diabaikan sebagian besar orang saat coding.

Anurag Sharma
sumber
2
PHP tidak mendefinisikan tipe pengembalian dan OP menandai pertanyaan ini denganPHP
Purefan
1

Hanya ingin menambahkan contoh kapan Anda mungkin perlu menggunakan keduanya. Saat ini saya sedang menulis file handler terikat ke model database dalam solusi ERP tujuan umum.

  • Saya memiliki beberapa kelas abstrak yang menangani standar kasar dan juga beberapa fungsi khusus seperti konversi dan streaming untuk berbagai kategori file.
  • Antarmuka akses file mendefinisikan seperangkat metode umum yang diperlukan untuk mendapatkan, menyimpan, dan menghapus file.

Dengan cara ini, saya dapat memiliki beberapa templat untuk file yang berbeda dan satu set metode antarmuka umum dengan perbedaan yang jelas. Antarmuka memberikan analogi yang benar untuk metode akses daripada apa yang seharusnya dengan kelas abstrak dasar.

Lebih jauh ke depan ketika saya akan membuat adaptor untuk layanan penyimpanan file yang berbeda, implementasi ini akan memungkinkan antarmuka untuk digunakan di tempat lain dalam konteks yang sama sekali berbeda.

Umair Ahmed
sumber