Inheritance dan Polimorfisme - Kemudahan penggunaan vs Kemurnian

Dalam sebuah proyek tim kami adalah menggunakan daftar objek untuk melakukan operasi massal pada set data yang harus diproses dengan cara yang sama. Secara khusus, benda-benda yang berbeda idealnya undang-undang yang sama, yang akan sangat dengan mudah dicapai dengan polimorfisme. Masalah yang saya miliki dengan itu adalah bahwa warisan menyiratkan is a hubungan, daripada has a hubungan. Misalnya, beberapa benda-benda have a kerusakan kontra, tetapi untuk membuat ini mudah untuk digunakan dalam daftar objek, polimorfisme bisa digunakan kecuali yang akan menyiratkan is a hubungan yang tidak't menjadi kenyataan. (Orang is tidak a kerusakan kontra.)

Satu-satunya solusi yang bisa saya pikirkan adalah untuk memiliki anggota dari kelas kembali tepat jenis objek ketika secara implisit dicor bukan mengandalkan warisan. Itu akan lebih baik untuk melupakan is a / has a ideal dalam pertukaran untuk kemudahan pemrograman?

Edit: Untuk lebih spesifik, saya menggunakan C++, jadi menggunakan polimorfisme akan memungkinkan objek yang berbeda untuk "tindakan yang sama" dalam arti bahwa kelas turunan bisa berada dalam satu daftar dan dioperasikan oleh sebuah fungsi virtual dari base class. Penggunaan interface (atau meniru mereka melalui warisan) tampaknya seperti solusi aku akan bersedia untuk menggunakan.

Saya pikir anda harus mengimplementasikan antarmuka untuk dapat menegakkan memiliki hubungan (saya melakukan ini di C#):

public interface IDamageable
{
    void AddDamage(int i);
    int DamageCount {get;}
}

Anda bisa menerapkan hal ini pada benda-benda:

public class Person : IDamageable

public class House : IDamageable

Dan anda'd pastikan bahwa DamageCount properti dan memiliki metode untuk memungkinkan anda untuk menambahkan kerusakan, tanpa menyiratkan bahwa seseorang dan sebuah rumah terkait satu sama lain dalam suatu hirarki.

Komentar (0)
Larutan

Hal ini dapat dicapai dengan menggunakan multiple inheritance. Dalam kasus tertentu anda (C++), anda dapat menggunakan virtual murni kelas sebagai interface. Hal ini memungkinkan anda untuk memiliki beberapa warisan tanpa menciptakan ruang lingkup/ambiguitas masalah. Contoh:

class Damage {
    virtual void addDamage(int d) = 0;
    virtual int getDamage() = 0;
};

class Person : public virtual Damage {
    void addDamage(int d) {
        // ...
        damage += d * 2;
    }

    int getDamage() {
        return damage;
    }
};

class Car : public virtual Damage {
    void addDamage(int d) {
        // ...
        damage += d;
    }

    int getDamage() {
        return damage;
    }
};

Sekarang kedua Orang dan Mobil 'adalah sebuah' Kerusakan, yang berarti, mereka melaksanakan Kerusakan antarmuka. Penggunaan virtual murni kelas (sehingga mereka seperti interface) adalah kunci dan harus digunakan sering. Itu insulates perubahan masa depan dari mengubah seluruh sistem. Baca di tempat Terbuka-Tertutup Prinsip untuk informasi lebih lanjut.

Komentar (0)

Saya setuju dengan Jon, tetapi dengan asumsi anda masih memiliki kebutuhan untuk memisahkan kerusakan counter kelas, yang dapat anda lakukan:

class IDamageable {
  virtual DamageCounter* damage_counter() = 0;
};
class DamageCounter {
  ...
};

Masing-masing damageable kelas maka perlu untuk menyediakan mereka sendiri damage_counter() fungsi anggota. Kelemahan dari ini adalah bahwa hal itu menciptakan vtable untuk setiap damageable kelas. Anda dapat menggunakan:

class Damageable {
 public:
  DamageCounter damage_counter() { return damage_counter_; }
 private:
  DamageCounter damage_counter_;
};

Tapi banyak orang yang Tidak Keren dengan beberapa warisan ketika beberapa orang tua memiliki variabel anggota.

Komentar (0)

@Kevin

Biasanya ketika kita berbicara tentang 'adalah' lebih 'memiliki' kami're berbicara tentang Warisan vs Komposisi.

Um...kerusakan counter hanya akan menjadi atribut dari kelas turunan dan tidak't benar-benar dibahas dalam hal 'seseorang adalah kerusakan counter' sehubungan dengan pertanyaan anda.

Mengalami kerusakan counter sebagai atribut doesn't memungkinkan dia untuk beragam benda dengan kerusakan counter ke koleksi. Misalnya, orang-orang dan mobil-mobil mungkin keduanya memiliki kerusakan counter, tetapi anda dapat't memiliki vektor<Orang|Mobil> atau vektor<dengan::getDamage()> atau sesuatu yang serupa dalam banyak bahasa. Jika anda memiliki sebuah Objek umum kelas dasar, maka anda dapat mendorong mereka dalam cara yang sama, tapi kemudian anda dapat't mengakses getDamage() metode umum.

Itu adalah esensi dari pertanyaan-nya, seperti yang saya baca itu. "saya Harus melanggar adalah-a dan has-a demi merawat benda-benda tertentu seperti jika mereka adalah sama, meskipun mereka tidak't?"

Komentar (0)

"Melakukannya dengan benar" akan memiliki manfaat dalam jangka panjang, jika hanya karena seseorang menjaga sistem kemudian akan lebih mudah untuk memahami jika itu dilakukan dengan benar untuk memulai dengan.

Tergantung pada bahasa, anda mungkin memiliki opsi multiple inheritance, tapi biasanya interface sederhana membuat paling masuk akal. &Quot;mudah" maksud saya membuat sebuah antarmuka yang isn't mencoba untuk menjadi terlalu banyak. Lebih baik untuk memiliki banyak interface sederhana dan beberapa monolitik orang-orang. Tentu saja, selalu ada trade off, dan terlalu banyak antarmuka yang mungkin akan menyebabkan orang-orang yang "lupa" tentang...

Komentar (0)

@Andrew

tempat "bertindak yang sama" dan polimorfisme adalah benar-benar tidak berhubungan. Bagaimana polimorfisme membuatnya mudah untuk mencapai?

Mereka semua memiliki, misalnya, salah satu fungsi yang sama. Let's menyebutnya addDamage(). Jika anda ingin melakukan sesuatu seperti ini:

foreach (obj in mylist)
    obj.addDamage(1)

Kemudian anda perlu baik bahasa dinamis, atau anda membutuhkan mereka untuk memperpanjang dari parent class (atau interface). misalnya:

class Person : DamageCounter {}
class Car : DamageCounter {}

foreach (DamageCounter d in mylist)
    d.addDamage(1)

Kemudian, anda dapat memperlakukan Orang dan Mobil yang sama dalam tertentu yang sangat berguna keadaan.

Komentar (0)

Kadang-kadang itu's layak menyerah ideal untuk realistis. Jika itu's akan menyebabkan masalah besar untuk "melakukannya dengan benar" dengan tidak ada manfaat nyata, maka saya akan lakukan itu salah. Dengan mengatakan bahwa, saya sering berpikir itu's layak meluangkan waktu untuk melakukannya dengan benar, karena tidak perlu multiple inheritance meningkatkan kompleksitas, dan itu ** bisa berkontribusi untuk sistem yang kurang dipelihara. Anda benar-benar harus memutuskan apa yang's terbaik untuk keadaan anda.

Salah satu pilihan akan memiliki benda-benda ini menerapkan Damageable antarmuka, daripada mewarisi dari DamageCounter. Dengan cara ini, orang-orang memiliki-a kerusakan counter, tapi adalah damageable. (Saya sering menemukan antarmuka membuat banyak lebih masuk akal sebagai kata sifat dari kata benda.) Kemudian anda bisa konsisten kerusakan interface pada Damageable benda-benda, dan tidak mengekspos bahwa kerusakan counter yang mendasari pelaksanaan (kecuali jika anda perlu).

Jika anda ingin pergi template rute (dengan asumsi C++ atau yang serupa), anda bisa melakukan hal ini dengan mixin, tapi yang buruk bisa mendapatkan benar-benar cepat jika dilakukan dengan buruk.

Komentar (0)

Polimorfisme does tidak memerlukan inheritance. Polimorfisme adalah apa yang anda dapatkan ketika beberapa objek melaksanakan pesan yang sama tanda tangan (metode).

Komentar (0)

Biasanya ketika kita berbicara tentang 'adalah' lebih 'memiliki' kami're berbicara tentang Warisan vs Komposisi.

Um...kerusakan counter hanya akan menjadi atribut dari kelas turunan dan tidak't benar-benar dibahas dalam hal 'seseorang adalah kerusakan counter' sehubungan dengan pertanyaan anda.

Melihat ini:

http://www.artima.com/designtechniques/compoinh.html

Yang mungkin bisa membantu anda di sepanjang jalan.

@Derek: Dari kata-kata, saya berasumsi ada adalah dasar clase, setelah membaca kembali pertanyaan aku sekarang melihat apa yang dia's mendapatkan di.

Komentar (0)

Pertanyaan ini benar-benar membingungkan :/

Pertanyaan anda di bold adalah sangat terbuka dan memiliki sebuah jawaban dari "itu tergantung", tapi anda contoh doesn't benar-benar memberikan banyak informasi tentang konteks dari yang anda minta. Garis-garis ini membingungkan saya;

set data yang harus diproses dengan cara yang sama

Cara apa? Ini adalah set diproses oleh suatu fungsi? Kelas lain? Melalui fungsi virtual pada data?

Secara khusus, benda-benda yang berbeda idealnya undang-undang yang sama, yang akan sangat dengan mudah dicapai dengan polimorfisme

Ideal "bertindak yang sama" dan polimorfisme adalah benar-benar tidak berhubungan. Bagaimana polimorfisme membuatnya mudah untuk mencapai?

Komentar (0)