Kalıtım ve Çok Biçimlilik arasındaki temel fark nedir?


172

Bu soru ile bugün modül açık kitap sınavının sonunda sunuldum ve kendimi kaybettim. Okuyordum Head first Javave her iki tanım da tamamen aynı görünüyordu. Sadece kendi aklıma gelen ANA farkın ne olduğunu merak ediyordum. Buna benzer bir dizi soru olduğunu biliyorum ama kesin bir cevap veren hiçbiri görmedim.


2
Bir şekilde bu soru ile ilgili: Polimorfizm kalıtım olmadan mümkün mü
Edwin Dalorzo

Yanıtlar:


289

Kalıtım, bir 'sınıfın' mevcut bir 'sınıftan' türetildiği zamandır. Eğer bir Personsınıfınız varsa, o zaman tüm şeyleri Studentgenişleten Person, Student miras alan bir sınıfınız Personvar demektir. Kişi'deki alanlara / yöntemlere koyduğunuz erişim değiştiricileri hakkında bazı ayrıntılar vardır, ancak bu temel fikirdir. Örneğin, özel bir alan varsa Person, Studentkendi özel çünkü göremez ve özel alanlar alt sınıflar için görünmez olacaktır.

Çok biçimlilik, ne tür bir şeye bağlı olarak, programın hangi yöntemleri kullanması gerektiğine nasıl karar verdiğiyle ilgilidir. Eğer bir varsa Personbir olan, readyöntem ve bir var Studentuzandığı Personkendi uygulamasını olan, readbir varsa bağlı olarak çalışma zamanı tarafından sizin için belirlenen çağrılır yöntem Personveya Student. Biraz zorlaşır, ancak eğer böyle bir şey yaparsanız

Person p = new Student();
p.read();

Öğrenci üzerindeki okuma yöntemi çağrılır. Bu, eylemdeki polimorfizmdir. Bir çünkü bu atamayı yapabilir Student bir olduğunu Person , ancak çalışma zamanı gerçek türü olduğunu bilmek akıllı yeterli polduğunu Öğrenci .

Detayların diller arasında farklılık gösterdiğini unutmayın. Örneğin, javascript'te kalıtım yapabilirsiniz, ancak Java'da çalışma biçiminden tamamen farklıdır.


9
@ hvgtcodes kısaca, üst sınıf-alt sınıf ilişkisi kalıtımdır ve aynı yöntemin ebeveyn sınıfı ve alt sınıfları arasında farklı bir şekilde uygulanması kavramıdır ve duruma dayalı olarak adlandırılan polimorfizmdir. Doğrumuyum?
Muhammed Raihan Muhaimin

1
@hvgotcodes ama eğer söylemek Personbireyin readyöntem kamu erişim değiştiricisi kullanıyor olmaz, Studenterişim onları muktedir nesneleri? ve sonra Student s = new Student();daha kolay olmayacak mı? Ben aslında Polimorfizmin faydalarından gerçekten tam olarak yararlanamıyorum.
Scorpiorian83

1
@hvgotcodes Öğrenci s = yeni Öğrenci () işe yarar. Ama diyelim ki bu fikri kullanarak bir sürü kod yazdıktan sonra, bir hata yaptığınızı anlıyorsunuz. Kişi aslında bir öğrenci değil, bir öğretmendir. Yani basitçe Kişi p = yeni Öğrenci () 'den Kişi p = yeni Öğretmen ()' e dönüşebilirsiniz, o zaman hayatınızı çok daha basit hale getirecektir.
munmunbb

Buradaki sorum neden Person p = new Student();yerine kullanmak istersiniz Student p = new Student();?
PerfectContrast

@PerfectContrast Öğrenci, şoför, öğretmen vb.Kişeyi Kişi olarak kullanmak ve bunları bir Liste veya başka bir şey altında gruplamak istediğinizde yararlı olduğunu düşünüyorum. Herkes için 'okuma' dediğinizde, herkes kendi 'okuma' yöntemini çağırır.
savante

205

Kalıtım , bir alt sınıfta bir süper sınıfın yapısını ve davranışını kullanmayı ifade eder .

Çok biçimlilik , alt sınıftaki bir süper sınıfın davranışını değiştirmeyi ifade eder .


5
Bu cevap, polimorfizmin kalıtım gerektirdiğini ima ediyor mu?
jaco0646

6
@ jaco0646 - Java bağlamında sanırım. (Diğer dillerde, belki de çok fazla değil.) Burada "süper sınıf" ve "alt sınıf" ın gevşek kullanıldığını unutmayın. Polimorfizm, aynı zamanda, bir arabirimde belirtilen (ama uygulanmayan) davranışın kalıtımı anlamına da gelebilir.
Ted Hopp

1
@AlirezaRahmani - Yorumunuzu anlamıyorum. Yani kalıtım hem özellikleri hem de davranışı miras almayı içermiyor mu? Bu, Java'nın (ve çoğu sınıfa dayalı, nesne yönelimli dillerin) mirası nasıl tanımladığının tersidir. Gönderen Java Dil Şartname, §8.4.8 : "A sınıfı C INHERITS doğrudan üst tüm beton yöntemleri m(hem staticve instanceiçin superclass ve ...)" (miras konusundaki ayrıntılar ardından). Bana "kodun yeniden kullanımı" gibi geliyor.
Ted Hopp

@TedHopp Kalıtım öncelikle bir polimorfik araçtır, ancak bazı insanlar, daha sonraki tehlikelerine göre, kodu yeniden kullanma / paylaşma yolu olarak kullanmaya çalışırlar. Gerekçe "miras alırsam bütün yöntemleri bedavaya alırsam iyi" dir, ancak bu iki sınıfın potansiyel olarak polimorfik bir ilişkisi olmadığı gerçeğini göz ardı eder.
Alireza Rahmani Khalili

1
@AlirezaRahmani - Java'da (OP'nin etiketlere göre özel olarak sorduğu şey budur), sınıf mirası kesinlikle davranışların miras alınmasını içerir. Bu dil tanımının bir parçası. Açıkladığınız gibi bunun kötüye kullanılması Java'nın zayıf yönlerinden biridir. (İlgili bir zayıflık, yalnızca arabirimde tanımlanan sabitleri içe aktarmak için arabirimleri uygulamak üzere sınıfların bildirilmesini içeriyordu. Sonunda Java tasarımcıları import static, arabirimlerin bu yanlış kullanımını ortadan kaldırmak için tanıtıldı .) Java'daki saf polimorfizm için, kullanılacak araç sınıf kalıtım değil arabirimlerdir.
Ted Hopp

63

Polimorfizm : Farklı türdeki nesnelere benzer şekilde davranma yeteneği. Örnek: Zürafa ve Timsah hem Hayvanlar hem de hayvanlar olabilir Move. Eğer bir örneğiniz Animalvarsa, Movene tür bir hayvan olduğunu bilmeden veya önemsemeden arayabilirsiniz .

Kalıtım : Bu, aynı zamanda hem polimorfizm hem de kodun yeniden kullanılmasını sağlamanın bir yoludur.

Diğer polimorfizm formları : Sadece polimorfizm sağlayan ancak kodun yeniden kullanılmadığı arayüzler gibi polimorfizme ulaşmanın başka bir yolu vardır (bazen Movebir Yılan gibi kod oldukça farklıdır, bu Movedurumda bir Köpek için oldukça farklı olabilir) bir Arayüz bu durumda daha iyi polimorfik bir seçim olacaktır.

Diğer dinamik dillerde polimorfizm, sınıfların aynı temel sınıfı veya arabirimi paylaşması bile gerekmeyen Duck Typing ile elde edilebilir, sadece aynı ada sahip bir yönteme ihtiyaçları vardır. Veya Javascript gibi daha dinamik, sınıflara bile ihtiyacınız yok, sadece aynı yöntem adına sahip bir nesne polimorfik olarak kullanılabilir.


17

Temel fark, polimorfizm kalıtımın spesifik bir sonucudur. Çok biçimlilik, çalıştırılacak yöntemin çalışma zamanında nesnenin türüne göre belirlendiği yerdir. Bu, bir sınıfın başka bir sınıftan miras alıp belirli bir yöntemi geçersiz kıldığı zaman ortaya çıkan bir durumdur. Bununla birlikte, normal bir miras ağacında herhangi bir yöntemi geçersiz kılmak zorunda değilsiniz ve bu nedenle tüm yöntem çağrılarının polimorfik olması gerekmez. bu mantıklı mı? Bu, tüm Ford araçları otomobiller için benzer bir sorundur, ancak tüm otomobiller Fords değildir (tam olarak olmasa da ...).

Ek olarak, polimorfizm yöntem çağırma ile ilgilenirken, kalıtım da veri üyelerini vb.


12

Java'da ikisi birbiriyle yakından ilişkilidir. Bunun nedeni Java'nın "dinamik gönderme" adı verilen yöntem çağırma için bir teknik kullanmasıdır. Sahip olursam

public class A {
  public void draw() { ... }
  public void spin() { ... }
}

public class B extends A {
  public void draw() { ... }
  public void bad() { ... }
}

...

A testObject = new B();

testObject.draw(); // calls B's draw, polymorphic
testObject.spin(); // calls A's spin, inherited by B
testObject.bad(); // compiler error, you are manipulating this as an A

Sonra B'nin spinA'dan miras aldığını görüyoruz . Ancak, nesneyi A tipiymiş gibi manipüle etmeye çalıştığımızda hala B'nin davranışını alıyoruz draw. drawDavranış polimorfik olduğunu.

Bazı dillerde, polimorfizm ve kalıtım o kadar yakından ilişkili değildir. Örneğin, C ++ 'da sanal olarak bildirilmeyen işlevler devralınır, ancak dinamik olarak gönderilmez, bu nedenle miras kullandığınızda bile bu polimorfik davranışı alamazsınız.

Javascript'te, her işlev çağrısı dinamik olarak gönderilir ve zayıf yazmaya sahip olursunuz. Bu, her biri kendi olan bir grup ilişkisiz nesneye sahip olabileceğiniz, drawüzerinde yinelenen bir fonksiyona sahip olabileceğiniz ve fonksiyonu çağırabileceğiniz anlamına gelir ve her biri iyi davranır. Kalıtım gerekmeksizin kendi polimorfik çekişiniz olurdu.


12

Çok biçimlilik: Kalem satan bir şirket için çalıştığınızı varsayalım. Böylece bir kalem hakkında bilmeniz gereken her şeyi işleyen "Kalem" adında çok güzel bir sınıf oluşturuyorsunuz. Tüm kalem sınıfını kullanarak faturalandırma, gönderim, fatura oluşturma için her türlü sınıfı yazarsınız. Bir gün patron geliyor ve "Harika bir haber! Şirket büyüyor ve şimdi Kitaplar & CD'ler satıyoruz!" Harika bir haber değil çünkü artık Kitap ve CD'yi kullanmak için Kalem kullanan her sınıfı değiştirmek zorundasınız. Ama başlangıçta "SellableProduct" adlı bir arayüz oluşturduysanız ve Pen bu arayüzü uyguladıysa. Daha sonra, Kalem yerine bu arayüzü kullanmak için tüm nakliye, fatura vb. Sınıflarınızı yazmış olabilirsiniz. Şimdi yapmanız gereken tek şey, SellableProduct arayüzünü uygulayan Book & CompactDisc adlı yeni bir sınıf yaratmak. Polimorfizm nedeniyle, diğer tüm sınıflar değişmeden çalışmaya devam edebilir! Mantıklı olmak?

Yani, polimorfizme ulaşmanın yollarından biri olan Kalıtım kullanmak anlamına gelir.

Bir sınıf / arayüzde polimorfizm mümkün olabilir, ancak kalıtım her zaman 2 VEYA daha fazla sınıf / arayüz arasındadır. Kalıtım her zaman "is-a" ilişkisine uygundur, oysa her zaman Polimorfizm (her ikisi de "is-a" / "has-a" ilişkisine uygun olabilir).


6

Kalıtım daha statik bir şeydir (bir sınıf diğerini uzatır), polimorfizm dinamik / çalışma zamanı bir şeydir (bir nesne, statik / bildirim türüne göre değil, dinamik / çalışma zamanı türüne göre davranır).

Örneğin

// This assignment is possible because B extends A
A a = new B();
// polymorphic call/ access
a.foo();

-> a'nın statik / bildirim türü A olmasına rağmen, gerçek dinamik / çalışma zamanı türü B'dir ve dolayısıyla a.foo (), A'da değil B'de tanımlandığı gibi foo yürütür.


3

Polimorfizm, benzer özelliklere sahip nesne türleri arasındaki ortak davranışı ifade etmeye yönelik bir yaklaşımdır. Ayrıca, bu özelliklerin varyasyonlarının geçersiz kılma yoluyla oluşturulmasına izin verir. Kalıtım, nesnelerin ilişkileri ve soyut davranışları ifade ettiği bir nesne hiyerarşisi yoluyla polimorfizme ulaşmanın bir yoludur. Yine de polimorfizme ulaşmanın tek yolu bu değildir. Prototip, kalıtımdan farklı olan polimorfizmi ifade etmenin başka bir yoludur. JavaScript, prototip kullanan bir dile örnektir. Başka yollar da olduğunu hayal ederdim.


3

Kalıtım, kodun yeniden kullanımı ile ilgili bir kavramdır. Örneğin ben bir üst sınıf söz sahibi olmadığını Animalve belirli özelliklerini ve yöntemlerini (bu örnek söz hakkından için içerir makeNoise()ve sleep()) ve ben olarak adlandırılan iki çocuk sınıfları oluşturmak Dogve Cat. Hem köpekler hem de kediler aynı şekilde uyuduklarından (varsayalım) ana sınıftaki sleep()yönteme Dogve Catalt sınıflara daha fazla işlevsellik eklemeye gerek yoktur Animal. Ancak, bir Dogkabuk ve bir Catmiyav öyleAnimalsınıf bir gürültü yapmak için bir yönteme sahip olabilir, bir köpek ve bir kedi birbirlerine ve diğer hayvanlara göre farklı sesler çıkarır. Bu nedenle, bu davranışı belirli türleri için yeniden tanımlamaya ihtiyaç vardır. Böylece polimorfizmin tanımı. Bu yardımcı olur umarım.


3

Oracle belgeleri farkı tam olarak aktardı.

kalıtım: Bir sınıf, alanları doğrudan ya da dolaylı olarak tüm sınıflarından miras alır . Alt sınıf, devraldığı yöntemleri geçersiz kılabilir veya devraldığı alanları veya yöntemleri gizleyebilir . (Alanları gizlemenin genellikle kötü programlama uygulaması olduğunu unutmayın.)

polimorfizm: polimorfizm biyolojide bir organizmanın veya türün birçok farklı biçime veya aşamaya sahip olabileceği bir prensibi ifade eder. Bu ilke, nesne yönelimli programlama ve Java dili gibi diller için de uygulanabilir. Bir sınıfın alt sınıfları kendi benzersiz davranışlarını tanımlayabilir ve yine de üst sınıfın aynı işlevlerinden bazılarını paylaşabilir.

polimorfizm alanlar için geçerli değildir.

İlgili yazı:

Çok Biçimlilik vs Geçersiz Kılma


1

Polimorfizm kalıtımın bir etkisidir . Sadece birbirini uzatan sınıflarda olabilir. Sınıfın tam türünü bilmeden bir sınıfın yöntemlerini çağırmanıza izin verir. Ayrıca, polimorfizm çalışma zamanında gerçekleşir .

Örneğin, Java polimorfizmi örneği:

resim açıklamasını buraya girin

Kalıtım, türetilmiş sınıfların temel sınıflarının arabirimlerini ve kodlarını paylaşmasına izin verir. Derleme zamanında olur .

Örneğin, Java Platformundaki Tüm Sınıflar Nesnenin Torunlarıdır (Oracle'ın resmi izniyle):

resim açıklamasını buraya girin

Java kalıtım ve Java polimorfizmi hakkında daha fazla bilgi edinmek


0

Kalıtım, A sınıfı, tüm ebeveynlerinden korunan / herkese açık yöntemleri / alanları tüm ebeveynlerinden Object'e kadar devraldığı zamandır.


0

JAVA kullanıyorsanız bu kadar basit:

Polimorfizm kalıtsal yöntemler kullanıyor, ancak farklı bir şey yapmak için onları geçersiz kılıyor (veya super diyorsan aynı şekilde teknik olarak polimorfik olmaz).

Yanlışsam düzelt.


0

Çok biçimliliğin temel amacı : Süper sınıfa referans değişkeni oluşturmak ve alt sınıf nesnesini tutmak => bir nesne birden fazla davranış gerçekleştirebilir .

In miras , alt sınıf özelliklerini devralır süper sınıfa .


0

kalıtım bir çeşit polimorfizmdir, tam olarak kalıtım dinamik polimorfizmdir. Yani, miras kaldırdığınızda, artık geçersiz kılamazsınız.


0

İle Kalıtım uygulama üst sınıfta tanımlanmış olan - yani davranış kalıtsaldır.

class Animal
{
  double location;
  void move(double newLocation)
  {
    location = newLocation;
  }
}

class Dog extends Animal;

İle Polimorfizminin yani sadece - uygulama alt sınıfta tanımlanan arayüz kalıtsaldır.

interface Animal
{
  void move(double newLocation);
}

class Dog implements Animal
{
  double location;
  void move(double newLocation)
  {
    location = newLocation;
  }
}

0

Polimorfizm , Antalya'da Kalıtım ile sağlanmıştır Java.

├── Animal
└── (instances)
    ├── Cat
    ├── Hamster
    ├── Lion
    └── Moose

├── interface-for-diet
   ├── Carnivore
   └── Herbivore
├── interface-for-habitat
   ├── Pet
   └── Wild

public class Animal {
    void breath() {
    };
}

public interface Carnivore {
    void loveMeat();
}

public interface Herbivore {
    void loveGreens();
}

public interface Pet {
    void liveInside();
}

public interface Wild {
    void liveOutside();
}

public class Hamster extends Animal implements Herbivore, Pet {

    @Override
    public void liveInside() {
        System.out.println("I live in a cage and my neighbor is a Gerbil");
    }

    @Override
    public void loveGreens() {
        System.out.println("I eat Carrots, Grapes, Tomatoes, and More");
    }
}

public class Cat extends Animal implements Carnivore, Pet {
    @Override
    public void liveInside() {
        System.out.println("I live in a cage and my neighbr is a Gerbil");
    }

    @Override
    public void loveMeat() {
        System.out.println("I eat Tuna, Chicken, and More");
    }
}

public class Moose extends Animal implements Herbivore, Wild {

    @Override
    public void liveOutside() {
        System.out.println("I live in the forest");
    }

    @Override
    public void loveGreens() {
        System.out.println("I eat grass");
    }
}

public class Lion extends Animal implements Carnivore, Wild {

    @Override
    public void liveOutside() {
        System.out.println("I live in the forest");
    }

    @Override
    public void loveMeat() {
        System.out.println("I eat Moose");
    }
}

HamsterSınıf devralır yapısı ile ilgili Animal, Herbivoreve Petsergileme Polimorfik davranışçılığı bir iç pet.

Catsınıfı alır yapısı ile ilgili Animal, Carnivoreve Petaynı zamanda sergileyen polimorfik davranışçılığı bir iç pet.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.