JavaRush /Java блогу /Random-KY /Java тилиндеги полиморфизм

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

Группада жарыяланган
OOP жөнүндө суроолор IT-компаниясында Java иштеп чыгуучусунун орду үчүн техникалык интервьюнун ажырагыс бөлүгү болуп саналат. Бул макалада биз OOP принциптеринин бири - полиморфизм жөнүндө сүйлөшөбүз. Биз интервью учурунда көп суралган аспектилерге токтолобуз, ошондой эле түшүнүктүү болуу үчүн чакан мисалдарды келтиребиз.

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

Полиморфизм – бул an objectтин конкреттүү түрү жөнүндө маалыматсыз эле интерфейси бар an objectтерди программанын бирдей колдонуу мүмкүнчүлүгү. Эгер сиз полиморфизм деген эмне деген суроого ушинтип жооп берсеңиз, сизден эмнени айткыңыз келгенин түшүндүрүп берүүңүз суралат. Дагы бир жолу, бир топ кошумча суроолорду бербестен, маектеш үчүн баарын иретке келтириңиз.

Интервьюда Javaдагы полиморфизм - 1
Биз OOP мамилеси класстарга негизделген an objectтердин өз ара аракеттенүүсүнө негизделген Java программасын курууну камтыганынан баштасак болот. Класстар алдын ала жазылган чиймелер (шаблондор), ага ылайык программадагы an objectилер түзүлөт. Андан тышкары, класстын ар дайым белгилүү бир түрү бар, ал жакшы программалоо стor менен өз максатын аты менен "айтып берет". Андан тышкары, Java катуу терилген тил болгондуктан, өзгөрмөлөрдү жарыялоодо программанын codeу дайыма an objectтин түрүн көрсөтүүсү керек экендигин белгилей кетүү керек. Буга катаал терүү codeдун коопсуздугун жана программанын ишенимдүүлүгүн жогорулатат жана компиляция стадиясында типтин туура келбеген каталарын (мисалы, сапты санга бөлүү аракети) алдын алууга мүмкүндүк берерин кошуңуз. Албетте, компилятор жарыяланган типти "билүү" керек - бул JDK классы же биз өзүбүз жараткан класс болушу мүмкүн. Сураныч, интервью берүүчүгө көңүл буруңуз, программалык code менен иштөөдө биз декларациялоодо ыйгарылган типтеги an objectтерди гана эмес, анын урпактарын да колдоно алабыз. Бул маанилүү жагдай: биз көптөгөн түрлөргө бир эле сыяктуу мамиле кылсак болот (ал типтер базалык типтен алынган болсо). Бул ошондой эле суперкласс түрүндөгү өзгөрмө жарыялап, биз ага анын тукумдарынын биринин маанисин ыйгара алабыз дегенди билдирет. Мисал келтирсеңиз интервью алган адамга жагат. Объекттердин тобу үчүн жалпы (негиз) боло турган an objectти тандаңыз жана андан бир нече класстарды мурастайт. Негизги класс:
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);
Биз суперкласс түрүнүн өзгөрмөсүн жарыялап, ага урпактардын биринин маанисин ыйгардык. Кыязы, сизден эмне үчүн компилятор дайындоо белгисинин сол жана оң жагында жарыяланган типтердин дал келбегендигине даттанbyte деп сурашат, анткени Java катаал терүүгө ээ. Жогору түрдөгү конversion бул жерде иштей турганын түшүндүрүңүз - an objectке шилтеме базалык класска шилтеме катары чечмеленет. Мындан тышкары, компилятор codeдо ушундай конструкцияга туш болуп, муну автоматтык түрдө жана кыйыр түрдө жасайт. DancerМисал codeунун негизинде дайындоо белгисинин сол жагында жарыяланган класс типинин оң жагында жарыяланган бир нече формалары (типтери) бар экенин көрсөтүүгө болот BreakDankDancer, ElectricBoogieDancer. Формалардын ар бири суперкласс методунда аныкталган жалпы функциялар үчүн өзүнүн уникалдуу жүрүм-турумуна ээ болушу мүмкүн dance. Башкача айтканда, суперкласста жарыяланган ыкма анын урпактарында башкача ишке ашырылышы мүмкүн. Бул учурда биз ыкманы жокко чыгаруу менен алектенип жатабыз жана дал ушул нерсе ар кандай формаларды (жүрүм-турумдарды) жаратат. Сиз муну аткаруу үчүн негизги метод codeун иштетүү аркылуу көрө аласыз: Программанын чыгышы Мен Антонмун, мен 18 жаштамын. Мен башкалардай эле бийлейм. Мен Алексей, мен 19 жаштамын. Мен брейк бийлейм! Мен Игорь, мен 20 жаштамын. Мен электр бугинги бийлейм! Эгерде биз урпактарда үстөмдүк кылууну колдонбосок, анда бизде башкача жүрүм-турум болбойт. Мисалы, класстарыбыздын ыкмасын түшүндүрүп берсек BreakDankDancer, программанын жыйынтыгы мындай болот: Мен Антонмун, мен 18 жаштамын. Мен башкалардай эле бийлейм. Мен Алексей, мен 19 жаштамын. Мен башкалардай эле бийлейм. Мен Игорь, мен 20 жаштамын. Мен башкалардай эле бийлейм. Бул жаңы класстарды түзүүнүн жөн эле мааниси жок дегенди билдирет . Java полиморфизминин принциби эмнеде? Программада an objectтин конкреттүү түрүн билбестен колдонуу кайда жашырылган? Биздин мисалда, бул түрдөгү an objectке чалуу ыкмасы . Java полиморфизми программага an objectтин же an objectтин кандай түрү болорун билүүнүн кереги жок дегенди билдирет . Негизгиси бул класстын тукуму . Ал эми урпактары жөнүндө сөз кыла турган болсок, анда белгилей кетүү керек, Java-да мурас гана эмес , ошондой эле . Азыр Java бир нече тукум куучулукту колдобой турганын эстен чыгарбоо керек – ар бир типте бир ата-эне (суперкласс) жана чексиз сандагы тукумдар (подкласстар) болушу мүмкүн. Ошондуктан, интерфейстер класстарга бир нече функцияларды кошуу үчүн колдонулат. Интерфейстер мураска салыштырмалуу an objectтердин ата-энеге кошулушун азайтат жана абдан кеңири колдонулат. Java тorнде интерфейс шилтеме түрү, ошондуктан программа типти интерфейс түрүнүн өзгөрмөсү деп жарыялай алат. Бул мисал келтирүүгө ылайыктуу учур. Келгиле, интерфейсти түзөлү: ElectricBoogieDancerdanceBreakDankDancerElectricBoogieDancerd.dance()dDancerBreakDankDancerElectricBoogieDancerDancerextendsimplements
public interface Swim {
    void swim();
}
Түшүнүктүү болушу үчүн, келгиле, ар кандай жана байланышпаган an objectтерди алып, аларда интерфейсти ишке ашыралы:
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();
}
Бул класстарда аныкталган методдор биздин an objectтер үчүн чакырылабы? Программаны аткарууда методдун керектүү ишке ашырылышын кантип тандайсыз? Бул суроолорго жооп берүү үчүн, биз кеч (динамикалык) байлоо жөнүндө сөз кылышыбыз керек. Байланыш деп биз метод чакырыгы менен анын класстарда конкреттүү ишке ашырылышынын ортосундагы байланышты түзүүнү билдирет. Негизи, code класстарда аныкталган үч ыкманын кайсынысы аткарыла турганын аныктайт. Java демейки боюнча кеч байланышты колдонот (эрте туташтыруудагыдай компиляция убагында эмес, аткаруу убагында). Бул codeду түзүүдө дегенди билдирет
for (Swim s : swimmers) {
            s.swim();
}
компилятор али codeдун кайсы класстан Humanэкенин Fishже Uboatал swim. Бул динамикалык жөнөтүү механизминин аркасында программа аткарылганда гана аныкталат - программаны аткаруу учурунда an objectтин түрүн текшерүү жана ушул типке методдун керектүү ишке ашырылышын тандоо. Эгер сизден бул кандайча ишке ашырылып жаткандыгы суралса, сиз an objectтерди жүктөөдө жана инициализациялоодо JVM жадыбалда tableларды курат жана аларда өзгөрмөлөрдү алардын маанилери менен, ал эми an objectтерди алардын методдору менен байланыштырат деп жооп бере аласыз. Мындан тышкары, эгерде an object мураска алынса же интерфейсти ишке ашырса, алгач анын классында жокко чыгарылган методдордун бар-жогу текшерилет. Эгерде бар болсо, алар ушул түргө байланат, эгерде жок болсо, класста бир деңгээл жогору (ата-энеде) аныкталган метод изделет жана көп деңгээлдүү иерархияда тамырга чейин. OOPдогу полиморфизм жана аны программалык codeдо ишке ашыруу жөнүндө сөз кылып жатып, абстракттуу класстарды, ошондой эле интерфейстерди колдонуу менен базалык класстарды аныктоо үчүн абстракттуу сүрөттөмөлөрдү колдонуу жакшы практика экенин белгилейбиз. Бул практика абстракцияны колдонууга негизделген - жалпы жүрүм-турумду жана касиеттерди обочолонтуу жана аларды абстрактуу класстын ичине кошуу же жалпы жүрүм-турумду гана изоляциялоо - бул учурда интерфейсти түзөбүз. Интерфейстерге жана класстык мураска негизделген an objectтердин иерархиясын куруу жана долбоорлоо OOP полиморфизминин принцибин аткаруу үчүн зарыл шарт болуп саналат. Javaдагы полиморфизм жана инновациялар маселесине келсек, абстракттуу класстарды жана интерфейстерди түзүүдө Java 8ден баштап, негизги сөздү колдонуу менен базалык класстардагы абстракттуу методдордун демейки реализациясын жазууга мүмкүн экендигин айта алабыз default. Мисалы:
public interface Swim {
    default void swim() {
        System.out.println("Just floating");
    }
}
Кээде алар полиморфизм принциби бузулбашы үчүн базалык класстарда методдорду жарыялоо талаптары жөнүндө сурашы мүмкүн. Бул жерде баары жөнөкөй: бул ыкмалар статикалык , жеке жана акыркы болбошу керек . Private методду класста гана жеткorктүү кылат жана сиз аны тукумда жокко чыгара албайсыз. Static методду an objectтин эмес, класстын менчиги кылат, ошондуктан суперкласс ыкмасы дайыма чакырылат. Финал ыкманы өзгөрүлбөс жана мураскорлордон жашырат.

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

Полиморфизмди колдонуу бизге эмне берет деген суроо да туулат. Бул жерде сиз отоо чөпкө өтө терең кирбестен, кыскача жооп бере аласыз:
  1. Объекттин ишке ашырылышын алмаштырууга мүмкүндүк берет. Тест мына ушуга негизделет.
  2. Программанын кеңейүү мүмкүнчүлүгүн камсыздайт - келечекке пайдубал түзүү бир топ жеңилдейт. Учурдагы түрлөрдүн негизинде жаңы типтерди кошуу OOP стorнде жазылган программалардын функционалдуулугун кеңейтүүнүн эң кеңири таралган жолу болуп саналат.
  3. Жалпы типтеги же жүрүм-туруму бар an objectтерди бир коллекцияга же массивге бириктирүүгө жана аларды бир калыпта башкарууга мүмкүндүк берет (биздин мисалдарыбыздагыдай, бардыгын бийлейт - ыкма danceже сүзүү - ыкма swim).
  4. Жаңы типтерди түзүүдө ийкемдүүлүк: ата-эненин ыкмасын ишке ашырууну же балада аны жокко чыгарууну тандай аласыз.

Сапар үчүн бөлүү сөздөр

Полиморфизм принциби абдан маанилүү жана кеңири тема. Ал Javaнын OOP дээрлик жарымын жана тилдин негиздеринин жакшы бөлүгүн камтыйт . Сиз интервьюда бул принципти аныктоодон кутула албайсыз. Аны билбестик же түшүнбөстүк маектешүүгө чекит коюшу ыктымал. Андыктан тест алдында өз бorмиңизди текшерүүгө жалкоо болбоңуз жана керек болсо аны жаңыртыңыз.
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION