JavaRush /Java Blogu /Random-AZ /Java-da polimorfizm

Java-da polimorfizm

Qrupda dərc edilmişdir
OOP ilə bağlı suallar İT şirkətində Java tərtibatçısı vəzifəsi üçün texniki müsahibənin ayrılmaz hissəsidir. Bu yazıda biz OOP prinsiplərindən biri - polimorfizm haqqında danışacağıq. Müsahibələr zamanı tez-tez soruşulan aspektlərə diqqət yetirəcəyik, həmçinin aydınlıq üçün kiçik nümunələr təqdim edəcəyik.

Polimorfizm nədir?

Polimorfizm , proqramın bu obyektin xüsusi növü haqqında məlumat olmadan eyni interfeysə malik obyektlərdən eyni şəkildə istifadə etmək qabiliyyətidir. Əgər polimorfizm nədir sualına bu şəkildə cavab versəniz, çox güman ki, sizdən nə demək istədiyinizi izah etməyiniz xahiş olunacaq. Bir daha, bir dəstə əlavə sual vermədən, müsahibə verən üçün hər şeyi qaydasına salın.

Müsahibədə Java-da polimorfizm - 1
OOP yanaşmasının siniflərə əsaslanan obyektlərin qarşılıqlı əlaqəsinə əsaslanan Java proqramının qurulmasından başlaya bilərik. Siniflər əvvəlcədən yazılmış çertyojlardır (şablonlardır), onlara uyğun olaraq proqramda obyektlər yaradılır. Üstəlik, bir sinif həmişə yaxşı proqramlaşdırma üslubu ilə məqsədini adı ilə "deyən" xüsusi bir tipə malikdir. Bundan əlavə, qeyd etmək olar ki, Java güclü tipli bir dil olduğundan, proqram kodu dəyişənləri elan edərkən həmişə obyektin tipini göstərməlidir. Buna əlavə edin ki, ciddi yazma kodun təhlükəsizliyini və proqramın etibarlılığını artırır və tərtib mərhələsində tip uyğunsuzluğu xətalarının (məsələn, sətri nömrəyə bölmək cəhdi) qarşısını almağa imkan verir. Təbii ki, kompilyator elan edilmiş növü "bilməlidir" - bu JDK-dan bir sinif və ya özümüz yaratdığımız bir sinif ola bilər. Müsahibənin nəzərinə çatdıraq ki, proqram kodu ilə işləyərkən biz yalnız elan edərkən təyin etdiyimiz tipli obyektlərdən deyil, həm də onun törəmələrindən də istifadə edə bilərik. Bu vacib bir məqamdır: biz bir çox növə yalnız birmiş kimi baxa bilərik (nə qədər ki, bu növlər əsas tipdən əldə edilir). Bu həm də o deməkdir ki, supersinif tipli dəyişəni elan edərək ona onun nəslindən birinin dəyərini təyin edə bilərik. Nümunə versəniz, müsahibin xoşuna gələcək. Bir qrup obyekt üçün ümumi (əsas) ola biləcək bəzi obyektləri seçin və ondan bir neçə sinif miras alın. Əsas sinif:
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 "Я " + name + ", to me " + age + " years. " ;
    }
}
Nəsillərdə əsas sinif metodunu ləğv edin:
public class ElectricBoogieDancer extends Dancer {
    public ElectricBoogieDancer(String name, int age) {
        super(name, age);
    }
// overriding the base class method
    @Override
    public void dance() {
        System.out.println( toString() + "I dance electric boogie!");
    }
}

public class BreakDankDancer extends Dancer{

    public BreakDankDancer(String name, int age) {
        super(name, age);
    }
// overriding the base class method
    @Override
    public void dance(){
        System.out.println(toString() + "I'm breakdancing!");
    }
}
Java-da polimorfizm nümunəsi və proqramda obyektlərin istifadəsi:
public class Main {

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

        Dancer breakDanceDancer = new BreakDankDancer("Alexei", 19);// upcast to base type
        Dancer electricBoogieDancer = new ElectricBoogieDancer("Igor", 20); // upcast to base type

        List<Dancer> discotheque = Arrays.asList(dancer, breakDanceDancer, electricBoogieDancer);
        for (Dancer d : discotheque) {
            d.dance();// polymorphic method call
        }
    }
}
Metod kodunda sətirlərdə olanları maingöstərin :
Dancer breakDanceDancer = new BreakDankDancer("Alexei", 19);
Dancer electricBoogieDancer = new ElectricBoogieDancer("Igor", 20);
Biz superclass tipli dəyişən elan etdik və ona nəsillərdən birinin dəyərini təyin etdik. Çox güman ki, sizdən soruşulacaq ki, nə üçün tərtibçi tapşırıq işarəsinin solunda və sağında elan edilmiş növlər arasında uyğunsuzluqdan şikayət etməyəcək, çünki Java-da ciddi yazmaq var. Burada yuxarı tipli çevrilmənin işlədiyini izah edin - obyektə istinad əsas sinfə istinad kimi şərh olunur. Üstəlik, kodda belə bir konstruksiya ilə qarşılaşan kompilyator bunu avtomatik və gizli şəkildə edir. Nümunə kodu əsasında göstərmək olar ki, tapşırığın işarəsinin solunda elan edilən sinif tipinin sağ tərəfində Dancerelan edilmiş bir neçə forma (tip) var BreakDankDancer, ElectricBoogieDancer. Formaların hər biri superklass metodunda müəyyən edilmiş ümumi funksionallıq üçün özünəməxsus davranışa malik ola bilər dance. Yəni supersinifdə elan edilmiş metod onun nəslində fərqli şəkildə həyata keçirilə bilər. Bu halda biz metodun üstünlüyü ilə məşğul oluruq və müxtəlif formalar (davranışlar) yaradan məhz budur. Bunu icra üçün əsas metod kodunu işlətməklə görə bilərsiniz: Proqram çıxışı Mən Anton, mənim 18 yaşım var. Mən hamı kimi rəqs edirəm. Mən Aleksey, 19 yaşım var. Brekdans edirəm! Mən İqor, mənim 20 yaşım var. Mən elektrik boogie rəqs edirəm! Nəsillərdə üstünlüyü istifadə etməsək, fərqli davranışlar əldə etməyəcəyik. Məsələn, dərslərimiz üçün metodu şərh etsək BreakDankDancer, proqramın nəticəsi belə olacaq: Mən Anton, mənim 18 yaşım var. Mən hamı kimi rəqs edirəm. Mən Aleksey, 19 yaşım var. Mən hamı kimi rəqs edirəm. Mən İqor, mənim 20 yaşım var. Mən hamı kimi rəqs edirəm. və bu o deməkdir ki , yeni siniflər yaratmağın sadəcə mənası yoxdur . Java polimorfizminin prinsipi tam olaraq nədir? Proqramda obyektin konkret tipini bilmədən istifadə etmək harada gizlənir? Nümunəmizdə bu tipli bir obyekt üçün metod çağırışıdır . Java polimorfizmi o deməkdir ki, proqramın obyektin və ya obyektin hansı tip olacağını bilməsi lazım deyil . Əsas odur ki, sinfin nəslindəndir . Və nəsillər haqqında danışırıqsa, qeyd etmək lazımdır ki, Java-da miras yalnız deyil , həm də . İndi Java-nın çoxsaylı irsiyyəti dəstəkləmədiyini xatırlamağın vaxtıdır - hər bir növün bir valideyni (supersinif) və qeyri-məhdud sayda nəsli (alt sinifləri) ola bilər. Buna görə də, interfeyslər siniflərə çoxlu funksionallıq əlavə etmək üçün istifadə olunur. İnterfeyslər mirasla müqayisədə obyektlərin bir valideynə birləşməsini azaldır və çox geniş istifadə olunur. Java-da interfeys bir istinad növüdür, ona görə də proqram interfeys tipinin dəyişəni olaraq növü elan edə bilər. Nümunə vermək üçün yaxşı vaxtdır. İnterfeys yaradaq: ElectricBoogieDancerdanceBreakDankDancerElectricBoogieDancerd.dance()dDancerBreakDankDancerElectricBoogieDancerDancerextendsimplements
public interface Swim {
    void swim();
}
Aydınlıq üçün fərqli və əlaqəli olmayan obyektləri götürək və onlarda interfeys tətbiq edək:
public class Human implements Swim {
    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 inflatable ring.");
    }

    @Override
    public String toString() {
        return "Я " + name + ", to me " + age + " years. ";
    }

}

public class Fish implements Swim{
    private String name;

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

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

    }

public class UBoat implements Swim {

    private int speed;

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

    @Override
    public void swim() {
        System.out.println("The submarine is sailing, rotating the propellers, at a speed" + speed + " knots.");
    }
}
Metod main:
public class Main {

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

        List<Swim> swimmers = Arrays.asList(human, fish, boat);
        for (Swim s : swimmers) {
            s.swim();
        }
    }
}
İnterfeysdə müəyyən edilmiş polimorfik metodun icrasının nəticəsi həmin interfeysi həyata keçirən növlərin davranışındakı fərqləri görməyə imkan verir. Onlar metodun icrasının müxtəlif nəticələrindən ibarətdir swim. Nümunəmizi öyrəndikdən sonra müsahibimiz kodu icra edərkən bunun səbəbini soruşa bilərmain
for (Swim s : swimmers) {
            s.swim();
}
Bu siniflərdə müəyyən edilmiş metodlar obyektlərimiz üçün çağırılırmı? Proqramı icra edərkən metodun istədiyiniz icrasını necə seçirsiniz? Bu suallara cavab vermək üçün gec (dinamik) bağlama haqqında danışmaq lazımdır. Bağlama dedikdə metod çağırışı ilə onun siniflərdə xüsusi tətbiqi arasında əlaqə yaratmaq nəzərdə tutulur. Əsasən, kod siniflərdə müəyyən edilmiş üç metoddan hansının icra ediləcəyini müəyyən edir. Java standart olaraq gec bağlamadan istifadə edir (erkən bağlamada olduğu kimi tərtib zamanı deyil, iş vaxtında). Bu o deməkdir ki, kodu tərtib edərkən
for (Swim s : swimmers) {
            s.swim();
}
kompilyator hələ kodun hansı sinifdən olduğunu HumanFishya Uboatonun swim. Bu, yalnız dinamik göndərmə mexanizmi sayəsində proqram icra edildikdə - proqramın icrası zamanı obyektin tipinin yoxlanılması və bu tip üçün metodun istədiyiniz icrasının seçilməsi ilə müəyyən ediləcəkdir. Bunun necə həyata keçirildiyini soruşsanız, cavab verə bilərsiniz ki, obyektləri yükləyərkən və işə salarkən JVM yaddaşda cədvəllər qurur və onlarda dəyişənləri öz dəyərləri ilə, obyektləri isə metodları ilə əlaqələndirir. Bundan əlavə, əgər obyekt miras alınırsa və ya interfeys tətbiq edirsə, əvvəlcə onun sinfində ləğv edilmiş metodların mövcudluğu yoxlanılır. Əgər varsa, onlar bu tipə bağlanır, əgər yoxdursa, çoxsəviyyəli iyerarxiyada bir səviyyə yuxarı sinifdə (valideyndə) və s. kökə qədər müəyyən edilən metod axtarılır. OOP-də polimorfizm və onun proqram kodunda tətbiqi haqqında danışarkən qeyd edirik ki, mücərrəd siniflərdən, eləcə də interfeyslərdən istifadə edərək əsas sinifləri müəyyən etmək üçün mücərrəd təsvirlərdən istifadə etmək yaxşı təcrübədir. Bu təcrübə abstraksiyadan istifadəyə əsaslanır - ümumi davranış və xassələri təcrid edərək onları mücərrəd sinifə daxil etmək və ya yalnız ümumi davranışı təcrid etmək - bu halda biz interfeys yaradırıq. İnterfeyslərə və sinif irsiyyətinə əsaslanan obyektlərin iyerarxiyasının qurulması və layihələndirilməsi OOP polimorfizmi prinsipinin yerinə yetirilməsi üçün ilkin şərtdir. Java-da polimorfizm və innovasiyalar məsələsinə gəlincə, qeyd edə bilərik ki, mücərrəd siniflər və interfeyslər yaradılarkən Java 8-dən başlayaraq açar sözündən istifadə etməklə əsas siniflərdə mücərrəd metodların standart tətbiqini yazmaq mümkündür default. Misal üçün:
public interface Swim {
    default void swim() {
        System.out.println("Just floating");
    }
}
Bəzən polimorfizm prinsipinin pozulmaması üçün əsas siniflərdə metodların elan edilməsinə dair tələblər barədə soruşa bilərlər. Burada hər şey sadədir: bu üsullar statik , şəxsiyekun olmamalıdır . Private metodu yalnız sinifdə əlçatan edir və siz onu nəsildə ləğv edə bilməzsiniz. Statik metodu obyektin deyil, sinfin xassəsinə çevirir, ona görə də superclass metodu həmişə çağırılacaq. Final metodu dəyişməz və varislərindən gizlədəcək.

Java-da polimorfizm bizə nə verir?

Çox güman ki, polimorfizmdən istifadənin bizə nə verdiyi sualı da ortaya çıxacaq. Burada alaq otlarına çox dərinləşmədən qısaca cavab verə bilərsiniz:
  1. Obyekt tətbiqlərini əvəz etməyə imkan verir. Sınaq buna əsaslanır.
  2. Proqramın genişləndirilməsini təmin edir - gələcək üçün təməl yaratmaq daha asan olur. Mövcud olanlar əsasında yeni növlərin əlavə edilməsi OOP üslubunda yazılmış proqramların funksionallığını genişləndirməyin ən geniş yayılmış üsuludur.
  3. Ümumi tipli və ya davranışı olan obyektləri bir kolleksiya və ya massivdə birləşdirməyə və onları vahid şəkildə idarə etməyə imkan verir (nümunələrimizdə olduğu kimi, hamını rəqs etmək - bir üsul dancevə ya üzmək - bir üsul swim).
  4. Yeni növlər yaratarkən çeviklik: siz valideyndən metod tətbiq etməyi və ya uşaqda onu ləğv etməyi seçə bilərsiniz.

Səyahət üçün ayrılıq sözləri

Polimorfizm prinsipi çox vacib və geniş mövzudur. O, Java-nın OOP proqramının demək olar ki, yarısını və dilin əsaslarının yaxşı bir hissəsini əhatə edir. Müsahibədə bu prinsipi müəyyən etməkdən yayına bilməyəcəksiniz. Onu bilməmək və ya səhv başa düşmək çox güman ki, müsahibəyə son qoyacaq. Odur ki, imtahandan əvvəl biliklərinizi yoxlamağa tənbəllik etməyin və lazım gələrsə təzələyin.
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION