CodeGym /Java Blogu /Rastgele /Java Polimorfizmi
John Squirrels
Seviye
San Francisco

Java Polimorfizmi

grupta yayınlandı
OOP ile ilgili sorular, bir BT şirketindeki Java geliştiricisi pozisyonu için teknik görüşmenin ayrılmaz bir parçasıdır. Bu yazıda, OOP'nin bir prensibi olan polimorfizmden bahsedeceğiz. Mülakatlar sırasında sıklıkla sorulan hususlara odaklanacağız ve netlik için birkaç örnek de vereceğiz.

Java'da polimorfizm nedir?

Polimorfizm, bir programın, nesnenin belirli türü hakkında bilgi olmadan, aynı arayüze sahip nesneleri aynı şekilde ele alma yeteneğidir. Polimorfizmin ne olduğu ile ilgili bir soruyu yanıtlarsanız, büyük olasılıkla ne demek istediğinizi açıklamanız istenecektir. Bir sürü ek soruyu tetiklemeden, hepsini görüşmeci için bir kez daha düzenleyin. Görüşme süresi: Java'da polimorfizm - 1OOP yaklaşımının, sınıflara dayalı nesneler arasındaki etkileşime dayalı bir Java programı oluşturmayı içerdiği gerçeğiyle başlayabilirsiniz. Sınıflar, programda nesneler oluşturmak için kullanılan önceden yazılmış taslaklardır (şablonlar). Ayrıca, bir sınıfın her zaman belirli bir türü vardır ve bu tür, iyi bir programlama stiliyle amacını ortaya koyan bir ada sahiptir. Ayrıca, Java güçlü bir şekilde yazıldığından, değişkenler bildirildiğinde program kodunun her zaman bir nesne türü belirtmesi gerektiğine dikkat çekilebilir. Buna, katı yazmanın kod güvenliğini ve güvenilirliğini iyileştirdiğini ve derleme sırasında bile uyumsuzluk türlerinden kaynaklanan hataları önlemeyi mümkün kıldığını (örneğin, bir diziyi bir sayıya bölmeye çalışmak) ekleyin. Doğal olarak, derleyici "bilmelidir" belirtilen tür – JDK'dan bir sınıf veya kendi oluşturduğumuz bir sınıf olabilir. Görüşmeciye, kodumuzun yalnızca bildirimde belirtilen türdeki nesneleri değil, aynı zamanda onun soyundan gelenleri de kullanabileceğini belirtin.Bu önemli bir nokta: Birçok farklı türle tek bir tür olarak çalışabiliriz (bu türlerin bir taban türünden türetilmesi şartıyla). Bu aynı zamanda, türü bir üst sınıf olan bir değişken bildirirsek, o değişkene alt türlerinden birinin bir örneğini atayabileceğimiz anlamına gelir. Bir örnek verirseniz görüşmeci hoşuna gidecektir. Birkaç sınıf tarafından (bir temel sınıf) paylaşılabilecek bir sınıf seçin ve birkaçını miras alın. Temel sınıf:

public class Dancer {
    private String name;
    private int age;

    public Dancer(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void dance() {
        System.out.println(toString() + " I dance like everyone else.");
    }

    @Override
    public String toString() {
        Return "I'm " + name + ". I'm " + age + " years old.";
    }
}
Alt sınıflarda, temel sınıfın yöntemini geçersiz kılın:

public class ElectricBoogieDancer extends Dancer {
    public ElectricBoogieDancer(String name, int age) {
        super(name, age);
    }
// Override the method of the base class
    @Override
    public void dance() {
        System.out.println(toString () + " I dance the electric boogie!");
    }
}

public class Breakdancer extends Dancer {

    public Breakdancer(String name, int age) {
        super(name, age);
    }
// Override the method of the base class
    @Override
    public void dance() {
        System.out.println(toString() + " I breakdance!");
    }
}
Bir polimorfizm örneği ve bu nesnelerin bir programda nasıl kullanılabileceği:

public class Main {

    public static void main(String[] args) {
        Dancer dancer = new Dancer("Fred", 18);

        Dancer breakdancer = new Breakdancer("Jay", 19); // Widening conversion to the base type 
        Dancer electricBoogieDancer = new ElectricBoogieDancer("Marcia", 20); // Widening conversion to the base type

        List<dancer> disco = Arrays.asList(dancer, breakdancer, electricBoogieDancer);
        for (Dancer d : disco) {
            d.dance(); // Call the polymorphic method
        }
    }
}
Ana yöntemde , satırların olduğunu gösterin

Dancer breakdancer = new Breakdancer("Jay", 19);
Dancer electricBoogieDancer = new ElectricBoogieDancer("Marcia", 20);
bir üst sınıfın değişkenini bildirin ve ona soyundan birinin örneği olan bir nesne atayın. Büyük olasılıkla, atama operatörünün sol ve sağ taraflarında bildirilen türlerin tutarsızlığında derleyicinin neden ters gitmediği sorulacaktır - sonuçta, Java güçlü bir şekilde yazılmıştır. Genişleyen bir tür dönüştürmenin burada iş başında olduğunu açıklayın — bir nesneye yapılan başvuru, onun temel sınıfına yapılan bir başvuru gibi ele alınır. Dahası, kodda böyle bir yapıyla karşılaşan derleyici, dönüştürmeyi otomatik ve dolaylı olarak gerçekleştirir. Örnek kod, atama operatörünün ( Dancer ) sol tarafında bildirilen türün, sağ tarafta ( Breakdancer , ElectricBoogieDancer ) bildirilen birden fazla forma (tür) sahip olduğunu gösterir.). Her form, üst sınıfta ( dans yöntemi) tanımlanan genel işlevselliğe göre kendi benzersiz davranışına sahip olabilir . Yani, bir üst sınıfta bildirilen bir yöntem, onun soyundan gelenlerde farklı şekilde uygulanabilir. Bu durumda, tam olarak birden çok form (davranış) yaratan şey olan yöntem geçersiz kılma ile uğraşıyoruz. Bu, ana yöntemdeki kodu çalıştırarak görülebilir: Program çıktısı: Ben Fred. 18 yaşındayım. Ben de herkes gibi dans ediyorum. Ben Jay'im. 19 yaşındayım. Breakdance yapıyorum! Ben Marcia'yım. 20 yaşındayım. Elektrikli boogie dansı yapıyorum! Alt sınıflardaki yöntemi geçersiz kılmazsak, farklı davranışlar elde edemeyiz. Örneğin,ElectricBoogieDancer sınıfları, ardından programın çıktısı şu olacaktır: Ben Fred. 18 yaşındayım. Ben de herkes gibi dans ediyorum. Ben Jay'im. 19 yaşındayım. Ben de herkes gibi dans ediyorum. Ben Marcia'yım. 20 yaşındayım. Ben de herkes gibi dans ediyorum. Ve bu, Breakdancer ve ElectricBoogieDancer sınıflarını oluşturmanın mantıklı olmadığı anlamına gelir . Polimorfizm ilkesi özellikle nerede ortaya çıkıyor? Belirli bir türü bilinmeden programda bir nesne nerede kullanılır? Örneğimizde, Dancer d nesnesinde dance() yöntemi çağrıldığında gerçekleşir . Java'da polimorfizm, programın nesnenin bir nesne olup olmadığını bilmesine gerek olmadığı anlamına gelir. Breakdancer veya ElectricBoogieDancer . Önemli olan Dancer sınıfının soyundan gelmesi. Ve torunlardan bahsederseniz, Java'daki kalıtımın yalnızca extensions olmadığını , aynı zamanda uyguladığını da not etmelisiniz.. Şimdi Java'nın çoklu kalıtımı desteklemediğini söylemenin zamanı geldi — her türün bir ebeveyni (üst sınıf) ve sınırsız sayıda alt sınıfı (alt sınıfları) olabilir. Buna göre, sınıflara birden çok işlev kümesi eklemek için arabirimler kullanılır. Alt sınıflarla (kalıtım) karşılaştırıldığında, arabirimler üst sınıfla daha az bağlantılıdır. Çok yaygın olarak kullanılırlar. Java'da arayüz bir referans tipidir, dolayısıyla program arayüz tipinin bir değişkenini bildirebilir. Şimdi bir örnek verme zamanı. Bir arayüz oluşturun:

public interface CanSwim {
    void swim();
}
Anlaşılır olması için, ilgisiz çeşitli sınıfları alıp arayüzü uygulamalarını sağlayacağız:

public class Human implements CanSwim {
    private String name;
    private int age;

    public Human(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public void swim() {
        System.out.println(toString()+" I swim with an inflated tube.");
    }

    @Override
    public String toString() {
        return "I'm " + name + ". I'm " + age + " years old.";
    }

}
 
public class Fish implements CanSwim {
    private String name;

    public Fish(String name) {
        this.name = name;
    }

    @Override
    public void swim() {
        System.out.println("I'm a fish. My name is " + name + ". I swim by moving my fins.");

    }

public class UBoat implements CanSwim {

    private int speed;

    public UBoat(int speed) {
        this.speed = speed;
    }

    @Override
    public void swim() {
        System.out.println("I'm a submarine that swims through the water by rotating screw propellers. My speed is " + speed + " knots.");
    }
}
ana yöntem:

public class Main {

    public static void main(String[] args) {
        CanSwim human = new Human("John", 6);
        CanSwim fish = new Fish("Whale");
        CanSwim boat = new UBoat(25);

        List<swim> swimmers = Arrays.asList(human, fish, boat);
        for (Swim s : swimmers) {
            s.swim();
        }
    }
}
Bir arabirimde tanımlanan polimorfik bir yöntemi çağıran sonuçlar, bu arabirimi gerçekleştiren türlerin davranışlarındaki farklılıkları bize gösterir. Bizim durumumuzda bunlar swim yöntemi tarafından görüntülenen farklı dizilerdir. Örneğimizi inceledikten sonra, görüşmeci neden bu kodu ana yöntemde çalıştırdığını sorabilir.

for (Swim s : swimmers) {
            s.swim();        
}
alt sınıflarımızda tanımlanan geçersiz kılma yöntemlerinin çağrılmasına neden olur? Program çalışırken yöntemin istenen uygulaması nasıl seçilir? Bu soruları cevaplamak için geç (dinamik) bağlamayı açıklamanız gerekir. Bağlama, bir yöntem çağrısı ile onun özel sınıf uygulaması arasında bir eşleme oluşturmak anlamına gelir. Temelde kod, sınıflarda tanımlanan üç yöntemden hangisinin yürütüleceğini belirler. Java, varsayılan olarak geç bağlamayı kullanır, yani bağlama, erken bağlamada olduğu gibi derleme zamanında değil çalışma zamanında gerçekleşir. Bunun anlamı, derleyici bu kodu derlediğinde

for (Swim s : swimmers) {
            s.swim();        
}
yüzerken yürütülecek kodun hangi sınıfın ( Human , Fish veya Uboat ) olduğunu bilmez.yöntem denir. Bu, dinamik bağlama mekanizması (çalışma zamanında bir nesnenin türünü kontrol etme ve bu tür için doğru uygulamayı seçme) sayesinde yalnızca program yürütüldüğünde belirlenir. Bunun nasıl uygulandığı sorulursa, JVM'nin nesneleri yüklerken ve başlatırken bellekte tablolar oluşturduğunu ve değişkenleri değerleriyle ve nesneleri yöntemleriyle bağladığını yanıtlayabilirsiniz. Bunu yaparken, bir sınıf miras alınırsa veya bir arabirim uygularsa, işin ilk sırası, geçersiz kılınan yöntemlerin varlığını kontrol etmektir. Varsa, bu türe bağlıdırlar. Değilse, eşleştirme yöntemi araması bir adım daha yüksek olan sınıfa (ebeveyn) ve çok düzeyli bir hiyerarşide köke doğru ilerler. OOP'de polimorfizm ve bunun kodda uygulanması söz konusu olduğunda, temel sınıfların soyut tanımlarını sağlamak için soyut sınıfları ve arayüzleri kullanmanın iyi bir uygulama olduğunu not ediyoruz. Bu uygulama, soyutlama ilkesinden yola çıkar - ortak davranış ve özellikleri tanımlayıp bunları soyut bir sınıfa koymak veya yalnızca ortak davranışı tanımlayıp onu bir arayüze yerleştirmek. Polimorfizmi uygulamak için arayüzlere ve sınıf kalıtımına dayalı bir nesne hiyerarşisi tasarlamak ve oluşturmak gerekir. Java'daki polimorfizm ve yeniliklerle ilgili olarak, Java 8'den başlayarak soyut sınıflar ve arayüzler oluştururken veya yalnızca ortak davranışı belirleyip bir arayüze yerleştirmek. Polimorfizmi uygulamak için arayüzlere ve sınıf kalıtımına dayalı bir nesne hiyerarşisi tasarlamak ve oluşturmak gerekir. Java'daki polimorfizm ve yeniliklerle ilgili olarak, Java 8'den başlayarak soyut sınıflar ve arayüzler oluştururken veya yalnızca ortak davranışı belirleyip bir arayüze yerleştirmek. Polimorfizmi uygulamak için arayüzlere ve sınıf kalıtımına dayalı bir nesne hiyerarşisi tasarlamak ve oluşturmak gerekir. Java'daki polimorfizm ve yeniliklerle ilgili olarak, Java 8'den başlayarak soyut sınıflar ve arayüzler oluştururkentemel sınıflarda soyut yöntemler için varsayılan bir uygulama yazmak için default anahtar sözcüğü. Örneğin:

public interface CanSwim {
    default void swim() {
        System.out.println("I just swim");
    }
}
Bazen görüşmeciler, polimorfizm ilkesinin ihlal edilmemesi için temel sınıflardaki yöntemlerin nasıl bildirilmesi gerektiğini sorar. Cevap basit: Bu yöntemler static , private veya final olmamalıdır . Özel, bir yöntemi yalnızca bir sınıf içinde kullanılabilir hale getirir, böylece onu bir alt sınıfta geçersiz kılamazsınız. Statik, bir yöntemi herhangi bir nesne yerine sınıfla ilişkilendirir, bu nedenle üst sınıfın yöntemi her zaman çağrılır. Ve final, bir yöntemi değişmez yapar ve alt sınıflardan gizlenir.

Polimorfizm bize ne verir?

Ayrıca büyük olasılıkla polimorfizmin bize nasıl fayda sağladığı da sorulacaktır. Saçma detaylara takılmadan kısaca cevaplayabilirsiniz:
  1. Sınıf uygulamalarını değiştirmeyi mümkün kılar. Test bunun üzerine kuruludur.
  2. Genişletilebilirliği kolaylaştırarak gelecekte üzerine inşa edilebilecek bir temel oluşturmayı çok daha kolaylaştırır. Mevcut türlere dayalı olarak yeni türler eklemek, OOP programlarının işlevselliğini genişletmenin en yaygın yoludur.
  3. Ortak bir türü veya davranışı paylaşan nesneleri tek bir koleksiyonda veya dizide birleştirmenize ve bunları tekdüze bir şekilde işlemenize olanak tanır (örneklerimizde olduğu gibi, herkesi dans etmeye() veya yüzmeye () zorladık :)
  4. Yeni türler yaratmada esneklik: Ebeveynin bir yöntemi uygulamasını seçebilir veya onu bir alt sınıfta geçersiz kılabilirsiniz.

Bazı ayrılık sözleri

Polimorfizm çok önemli ve kapsamlı bir konudur. Bu, Java'da OOP hakkındaki bu makalenin neredeyse yarısının konusudur ve dilin temelinin önemli bir bölümünü oluşturur. Bir röportajda bu prensibi tanımlamaktan kaçınamayacaksınız. Bunu bilmiyorsanız veya anlamıyorsanız, görüşme muhtemelen sona erecektir. Bu yüzden tembel olmayın - görüşmeden önce bilginizi değerlendirin ve gerekirse yenileyin.
Yorumlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION