JavaRush /Java блогы /Random-KK /Java тіліндегі полиморфизм

Java тіліндегі полиморфизм

Топта жарияланған
OOP туралы сұрақтар IT-компаниясындағы Java әзірлеушісі лауазымына арналған техникалық сұхбаттың ажырамас бөлігі болып табылады. Бұл мақалада біз OOP принциптерінің бірі - полиморфизм туралы айтатын боламыз. Біз сұхбат кезінде жиі сұралатын аспектілерге тоқталамыз, сонымен қатар түсінікті болу үшін шағын мысалдар келтіреміз.

Полиморфизм дегеніміз не?

Полиморфизм – бағдарламаның осы an objectінің нақты түрі туралы ақпаратсыз бірдей интерфейсі бар an objectілерді бірдей пайдалану мүмкіндігі. Егер сіз полиморфизм деген не деген сұраққа осылай жауап берсеңіз, сізден не айтқыңыз келетінін түсіндіру сұралады. Тағы да, көптеген қосымша сұрақтарды сұрамай, сұхбат алушы үшін бәрін ретке келтіріңіз.

Сұхбатта Java тіліндегі полиморфизм - 1
Біз OOP тәсілі класстарға негізделген an objectілердің өзара әрекеттесуіне негізделген Java бағдарламасын құруды көздейтінінен бастауға болады. Класстар – алдын ала жазылған сызбалар (шаблондар), соған сәйкес бағдарламада an objectілер құрылады. Сонымен қатар, сыныптың әрқашан белгілі бір түрі болады, ол жақсы бағдарламалау стилімен өз мақсатын атымен «айтады». Бұдан басқа, Java қатты терілген тіл болғандықтан, айнымалыларды жариялау кезінде бағдарлама codeы әрқашан an objectінің түрін көрсетуі керек екенін атап өтуге болады. Бұған қатаң теру codeтың қауіпсіздігі мен бағдарламаның сенімділігін арттыратынын және компиляция сатысында тип сәйкессіздік қателерінің (мысалы, жолды санға бөлу әрекеті) алдын алуға мүмкіндік беретінін қосыңыз. Әрине, компилятор жарияланған типті «білуі» керек - бұл JDK класы немесе біз өзіміз жасаған класс болуы мүмкін. Сұхбат алушыға бағдарлама codeымен жұмыс істеу кезінде біз декларациялау кезінде тағайындалған типтегі нысандарды ғана емес, сонымен бірге оның ұрпақтарын да пайдалана алатынымызды ескеріңіз. Бұл маңызды мәселе: біз көптеген түрлерді бір болғандай қарастыра аламыз (бұл түрлер негізгі түрден алынған болса). Бұл сонымен қатар суперкласс түріндегі айнымалыны жариялап, оған оның ұрпақтарының бірінің мәнін тағайындай алатынымызды білдіреді. Мысал келтірсеңіз, сұхбат алушыға ұнайды. Нысандар тобы үшін ортақ (негіз) болуы мүмкін кейбір нысанды таңдап, одан бірнеше сыныпты мұраға алыңыз. Негізгі класс:
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. " ;
    }
}
Ұрпақтарда негізгі сынып әдісін қайта анықтаңыз:
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 тіліндегі полиморфизмнің мысалы және бағдарламада an objectілерді пайдалану:
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
        }
    }
}
Әдіс codeында жолдарда не бар екенін mainкөрсетіңіз :
Dancer breakDanceDancer = new BreakDankDancer("Alexei", 19);
Dancer electricBoogieDancer = new ElectricBoogieDancer("Igor", 20);
Біз суперкласс түрінің айнымалы мәнін жариялап, оған ұрпақтардың бірінің мәнін тағайындадық. Сірә, сізден компилятор неліктен тағайындау белгісінің сол және оң жағында жарияланған түрлер арасындағы сәйкессіздікке шағымданбайды деген сұрақ туындайды, өйткені Java-да қатаң теру бар. Жоғары түрлендіру осы жерде жұмыс істейтінін түсіндіріңіз - нысанға сілтеме негізгі сыныпқа сілтеме ретінде түсіндіріледі. Сонымен қатар, компилятор codeта мұндай құрылымды кездестіріп, мұны автоматты түрде және жасырын түрде жасайды. DancerМысал codeына сүйене отырып, тағайындау белгісінің сол жағында жарияланған класс типінің оң жағында жарияланған бірнеше пішіндері (түрлері) бар екенін көрсетуге болады BreakDankDancer, ElectricBoogieDancer. Пішіндердің әрқайсысының суперкласс әдісінде анықталған жалпы функционалдылық үшін өзінің бірегей әрекеті болуы мүмкін dance. Яғни, суперкласста жарияланған әдіс оның ұрпақтарында басқаша жүзеге асырылуы мүмкін. Бұл жағдайда біз әдісті қайта анықтаумен айналысамыз және дәл осы нәрсе әртүрлі формаларды (мінез-құлықтарды) жасайды. Мұны орындау үшін негізгі әдіс codeын іске қосу арқылы көруге болады: Бағдарламаның шығуы Мен Антонмын, мен 18 жастамын. Мен басқалар сияқты билеймін. Мен Алексей, мен 19 жастамын. Мен брейк-данс жасаймын! Мен Игорь, мен 20 жастамын. Мен электрлі буги билеймін! Ұрпақтарда басымдылықты қолданбасақ, басқа мінез-құлық болмайды. BreakDankDancerМысалы, егер біз сыныптарымызға арналған ElectricBoogieDancerәдісті түсіндірсек dance, бағдарламаның нәтижесі келесідей болады: Мен Антонмын, мен 18 жастамын. Мен басқалар сияқты билеймін. Мен Алексей, мен 19 жастамын. Мен басқалар сияқты билеймін. Мен Игорь, мен 20 жастамын. Мен басқалар сияқты билеймін. BreakDankDancerжәне бұл дегеніміз, жаңа сыныптарды құрудың мағынасы жоқ ElectricBoogieDancer. Java полиморфизмінің принципі қандай? Программада an objectіні оның нақты түрін білмей пайдалану қайда жасырылады? Біздің мысалда бұл түрдегі d.dance()нысандағы әдісті шақыру . Java полиморфизмі бағдарламаға нысанның немесе нысанның қандай типті болатынын білудің қажеті жоқ екенін білдіреді . Ең бастысы , таптың ұрпағы . Ал ұрпақтар туралы айтатын болсақ, Java тіліндегі мұра тек қана емес , сонымен қатар . Енді Java бірнеше мұраға қолдау көрсетпейтінін есте ұстайтын уақыт келді - әр типте бір ата-ана (суперкласс) және ұрпақтардың (ішкі сыныптар) шексіз саны болуы мүмкін. Сондықтан интерфейстер сыныптарға бірнеше функционалдылықты қосу үшін пайдаланылады. Интерфейстер мұрагерлікпен салыстырғанда an objectілердің ата-анаға қосылуын азайтады және өте кең қолданылады. Java тілінде интерфейс анықтамалық тип болып табылады, сондықтан бағдарлама типті интерфейс түрінің айнымалысы деп жариялай алады. Бұл мысал келтіруге жақсы уақыт. Интерфейсті жасайық: dDancerBreakDankDancerElectricBoogieDancerDancerextendsimplements
public interface Swim {
    void swim();
}
Түсінікті болу үшін әртүрлі және бір-біріне қатысы жоқ нысандарды алайық және оларда интерфейсті енгізейік:
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.");
    }
}
Әдіс 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();
        }
    }
}
Интерфейсте анықталған полиморфты әдісті орындау нәтижесі сол интерфейсті жүзеге асыратын типтердің әрекетіндегі айырмашылықтарды көруге мүмкіндік береді. Олар әдісті орындаудың әртүрлі нәтижелерінен тұрады swim. Біздің мысалды зерттегеннен кейін интервьюер codeты орындаған кезде неге екенін сұрауы мүмкінmain
for (Swim s : swimmers) {
            s.swim();
}
Осы сыныптарда анықталған әдістер біздің нысандар үшін шақырылады ма? Бағдарламаны орындау кезінде әдістің қажетті орындалуын қалай таңдайсыз? Бұл сұрақтарға жауап беру үшін кеш (динамикалық) байланыстыру туралы айту керек. Байланыстыру арқылы біз әдісті шақыру мен оның сыныптарда нақты орындалуы арасындағы байланысты орнатуды айтамыз. Негізінде code сыныптарда анықталған үш әдістің қайсысы орындалатынын анықтайды. Java әдепкі бойынша кеш байланыстыруды пайдаланады (ерте байланыстырудағыдай компиляция уақытында емес, орындау уақытында). Бұл codeты құрастыру кезінде дегенді білдіреді
for (Swim s : swimmers) {
            s.swim();
}
Humanкомпилятор әлі codeтың қай класстан екенін Fishнемесе Uboatоның орындалатынын білмейді swim. Бұл динамикалық жіберу механизмінің арқасында бағдарлама орындалғанда ғана анықталады - бағдарламаны орындау кезінде an object түрін тексеру және осы түрге әдістің қажетті орындалуын таңдау. Егер сізден мұның қалай жүзеге асырылатынын сұраса, сіз an objectілерді жүктеп, инициализациялағанда JVM жадта кестелер құрастырады және оларда айнымалыларды мәндерімен, ал нысандарды әдістерімен байланыстырады деп жауап бере аласыз. Сонымен қатар, егер an object мұраланған болса немесе интерфейсті жүзеге асырса, алдымен оның класында қайта анықталған әдістердің болуы тексеріледі. Егер бар болса, олар осы түрге байланыстырылады, егер жоқ болса, сыныпта бір деңгей жоғары (ата-анада) анықталған әдіс ізделеді және т.б. көп деңгейлі иерархияда түбірге дейін. OOP-тағы полиморфизм және оны бағдарлама codeында жүзеге асыру туралы айта отырып, абстрактілі класстарды, сонымен қатар интерфейстерді пайдалана отырып, базалық сыныптарды анықтау үшін дерексіз сипаттамаларды пайдалану жақсы тәжірибе екенін атап өтеміз. Бұл тәжірибе абстракцияны қолдануға негізделген - жалпы мінез-құлық пен қасиеттерді оқшаулау және оларды абстрактілі сыныпқа қосу немесе тек жалпы әрекетті оқшаулау - бұл жағдайда интерфейс жасаймыз. Интерфейстерге және класстық мұраға негізделген an objectілер иерархиясын құру және жобалау OOP полиморфизмі принципін орындаудың міндетті шарты болып табылады. Java тіліндегі полиморфизм және инновациялар мәселесіне келетін болсақ, абстрактілі класстар мен интерфейстерді құру кезінде Java 8-ден бастап негізгі класстардағы дерексіз әдістердің әдепкі іске асырылуын кілт сөзді пайдаланып жазуға болатынын айта аламыз default. Мысалы:
public interface Swim {
    default void swim() {
        System.out.println("Just floating");
    }
}
Кейде олар полиморфизм принципі бұзылмауы үшін базалық сыныптарда әдістерді жариялауға қойылатын талаптар туралы сұрай алады. Мұнда бәрі қарапайым: бұл әдістер статикалық , жеке және соңғы болмауы керек . Private әдісті тек сыныпта қолжетімді етеді және сіз оны ұрпақта қайта анықтай алмайсыз. Static әдісті an object емес, сыныптың қасиеті етеді, сондықтан суперкласс әдісі әрқашан шақырылады. Финал әдісті өзгермейтін және мұрагерлерінен жасырады.

Полиморфизм бізге Java тілінде не береді?

Полиморфизмді қолдану бізге не береді деген сұрақ туындауы мүмкін. Мұнда сіз арамшөптерге терең бойламай қысқаша жауап бере аласыз:
  1. Нысан енгізулерін ауыстыруға мүмкіндік береді. Тестілеу осыған негізделген.
  2. Бағдарламаның кеңеюін қамтамасыз етеді - болашаққа негіз жасау оңайырақ болады. Қолданыстағыларға негізделген жаңа түрлерді қосу OOP стилінде жазылған бағдарламалардың функционалдығын кеңейтудің ең кең таралған тәсілі болып табылады.
  3. Жалпы түрі немесе мінез-құлқы бар нысандарды бір жинаққа немесе массивке біріктіруге және оларды біркелкі басқаруға мүмкіндік береді (біздің мысалдарымыздағыдай, барлығын билеу - әдіс danceнемесе жүзу - әдіс swim).
  4. Жаңа түрлерді жасау кезінде икемділік: ата-анадан әдісті енгізуді таңдауға немесе оны балада қайта анықтауға болады.

Саяхатқа арналған қоштасатын сөздер

Полиморфизм принципі өте маңызды және кең тақырып. Ол Java-ның OOP- тің жартысына жуығын және тіл негіздерінің жақсы бөлігін қамтиды. Сіз сұхбатта бұл принципті анықтаудан құтыла алмайсыз. Оны білмеу немесе түсінбеу сұхбатты аяқтауы мүмкін. Сондықтан тест алдында біліміңізді тексеруге ерінбеңіз және қажет болса оны жаңартып отырыңыз.
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION