JavaRush /Java блогы /Random-KK /Java тіліндегі көп мұра. Құрам және мұрагерлік
DSergey_Kh
Деңгей

Java тіліндегі көп мұра. Құрам және мұрагерлік

Топта жарияланған

Java тіліндегі бірнеше мұра

Көп мұра бірнеше суперсыныптардан мұра алатын класс жасауға мүмкіндік береді. Кейбір басқа танымал an objectіге бағытталған бағдарламалау тілдерінен айырмашылығы, мысалы, C++, Java сыныптардан бірнеше мұраға рұқсат бермейді. Java бірнеше класс мұрасын қолдамайды, себебі ол гауһар мәселесіне әкелуі мүмкін. Бұл мәселені шешу жолдарын іздеудің орнына, бірнеше мұрагерлік сияқты бірдей нәтижеге қол жеткізудің жақсы нұсқалары бар.

Алмаз мәселесі

Алмаз мәселесін оңайырақ түсіну үшін Java тілінде бірнеше мұраға қолдау көрсетіледі делік. Бұл жағдайда төмендегі суретте көрсетілгендей класс иерархиясы болуы мүмкін. Класс абстрактілі және онда қандай да бір әдіс жарияланған деп Java тіліндегі көп мұра.  Құрам және мұрагерлік - 1есептейік . SuperClassНақты класстардың екеуі де ClassAжәне ClassB.
package com.journaldev.inheritance;
public abstract class SuperClass {
	public abstract void doSomething();
}
package com.journaldev.inheritance;
public class ClassA extends SuperClass{
	@Override
	public void doSomething(){
		System.out.println("doSomething implementation of A");
	}
	//ClassA own method
	public void methodA(){
	}
}
package com.journaldev.inheritance;
public class ClassB extends SuperClass{
	@Override
	public void doSomething(){
		System.out.println("doSomething implementation of B");
	}
	//ClassB specific method
	public void methodB(){
	}
}
ClassCЕнді біз оны іске асырғымыз келеді делік және ClassAмен арқылы мұрагер болғымыз келеді ClassB.
package com.journaldev.inheritance;
public class ClassC extends ClassA, ClassB{
	public void test(){
		//calling super class method
		doSomething();
	}
}
Әдіс test()суперкласс әдісін шақыратынын ескеріңіз doSomething(). Бұл екіұштылыққа әкеледі, себебі компилятор қандай суперкласс әдісін орындау керектігін білмейді. Бұл алмаз есебі деп аталатын гауһар тәрізді класс диаграммасы. Бұл Java бірнеше мұраны қолдамауының басты себебі. Бірнеше класты мұрагерлікпен жоғарыда аталған мәселе кем дегенде бір жалпы әдісі бар үш сыныпта ғана орын алуы мүмкін екенін ескеріңіз.

Бірнеше интерфейстік мұра

Java тілінде бірнеше мұраға сыныптарда қолдау көрсетілмейді, бірақ интерфейстерде оған қолдау көрсетіледі. Және бір интерфейс көптеген басқа интерфейстерді кеңейте алады. Төменде қарапайым мысал келтірілген.
package com.journaldev.inheritance;
public interface InterfaceA {
	public void doSomething();
}
package com.journaldev.inheritance;
public interface InterfaceB {
	public void doSomething();
}
Екі интерфейс бірдей әдісті жариялайтынын ескеріңіз. Енді біз төмендегі мысалда көрсетілгендей осы интерфейстердің екеуін де кеңейтетін интерфейс жасай аламыз.
package com.journaldev.inheritance;
public interface InterfaceC extends InterfaceA, InterfaceB {
	//same method is declared in InterfaceA and InterfaceB both
	public void doSomething();
}
Бұл тамаша жұмыс істейді, себебі интерфейстер тек әдістерді жариялайды және іске асыру интерфейсті мұраға алатын сыныптарда орындалады. Осылайша, бірнеше интерфейс мұрасында екіұштылықты алудың ешқандай жолы жоқ.
package com.journaldev.inheritance;
public class InterfacesImpl implements InterfaceA, InterfaceB, InterfaceC {
	@Override
	public void doSomething() {
		System.out.println("doSomething implementation of concrete class");
	}
	public static void main(String[] args) {
		InterfaceA objA = new InterfacesImpl();
		InterfaceB objB = new InterfacesImpl();
		InterfaceC objC = new InterfacesImpl();

		//all the method calls below are going to same concrete implementation
		objA.doSomething();
		objB.doSomething();
		objC.doSomething();
	}
}
Кез келген суперкласс әдісін қайта анықтаған кезде немесе интерфейс әдісін іске асырғанда, annotationны пайдаланыңыз @Override. methodA()Егер біз сыныптың функциясын және сыныптың ClassAфункциясын сыныпта қолданғымыз келсе ше ? Шешім композицияны қолдануда жатыр. Төменде класс әдістерін де, нысандардың бірінің әдісін де анықтау үшін композицияны пайдаланатын класс нұсқасы берілген .methodB()ClassBClassCClassCdoSomething()
package com.journaldev.inheritance;
public class ClassC{
	ClassA objA = new ClassA();
	ClassB objB = new ClassB();
	public void test(){
		objA.doSomething();
	}
	public void methodA(){
		objA.methodA();
	}
	public void methodB(){
		objB.methodB();
	}
}

Құрам және мұрагерлік

Java бағдарламалаудың ең жақсы тәжірибелерінің бірі - «мұраға дейін құрамды бекіту». Біз бұл тәсілді қолдайтын кейбір аспектілерді қарастырамыз.
  1. Бізде суперкласс және оны кеңейтетін сынып бар делік:

    package com.journaldev.inheritance;
    public class ClassC{
    	public void methodC(){
    	}
    }
    package com.journaldev.inheritance;
    public class ClassD extends ClassC{
    	public int test(){
    		return 0;
    	}
    }

    Жоғарыдағы code құрастырылады және жақсы жұмыс істейді. ClassCБірақ, төменде көрсетілгендей сыныптың орындалуын өзгертсек ше :

    package com.journaldev.inheritance;
    public class ClassC{
    	public void methodC(){
    	}
    	public void test(){
    	}
    }

    Бұл әдіс test()ішкі сыныпта бұрыннан бар екенін ескеріңіз, бірақ қайтару түрі басқа. Енді сынып ClassDкомпиляцияланбайды және егер сіз кез келген IDE қолдансаңыз, ол суперкласс немесе қосалқы сыныптағы қайтару түрін өзгертуді ұсынады.

    Енді бізде көп деңгейлі класс мұрагерлігі иерархиясы бар және суперклассқа қол жеткізе алмайтын жағдайды елестетіп көріңіз. Компиляция қатесін жою үшін біздің қосалқы сынып әдісінің қолтаңбасын немесе оның атын өзгертуден басқа амалымыз болмайды. Біз сондай-ақ қосалқы класс әдісін ол аталатын барлық жерлерде өзгертуге тура келеді. Осылайша, мұра біздің codeты сынғыш етеді.

    Жоғарыда аталған мәселе композицияда ешқашан болмайды және бұл оны мұраға тартымды етеді.

  2. Мұрагерлікпен байланысты тағы бір мәселе - біз клиентке суперкласстың барлық әдістерін көрсетеміз және егер біздің суперкласс дұрыс жобаланбаған болса және қауіпсіздік саңылаулары болса, онда біз сыныптың ең жақсы іске асырылуын жүзеге асырғанымызға қарамастан, бізге нашар енгізілу әсер етеді. суперкласстың. Композиция бізге суперкласс әдістеріне басқарылатын қолжетімділікті қамтамасыз етуге көмектеседі, ал мұрагерлік суперкласс әдістерін бақылауды қамтамасыз етпейді. Бұл да мұрадан композицияның негізгі артықшылықтарының бірі.

  3. Композицияның тағы бір артықшылығы - ол шақыру әдістерінде икемділікке мүмкіндік береді. Жоғарыда ұсынылған сыныпты жүзеге асыруымыз ClassCоңтайлы емес және компиляция уақытының шақырылатын әдіске байланысты болуын қамтамасыз етеді. Ең аз өзгерістермен біз әдісті шақыруды икемді және динамикалық ете аламыз.

    package com.journaldev.inheritance;
    public class ClassC{
    	SuperClass obj = null;
    	public ClassC(SuperClass o){
    		this.obj = o;
    	}
    	public void test(){
    		obj.doSomething();
    	}
    	public static void main(String args[]){
    		ClassC obj1 = new ClassC(new ClassA());
    		ClassC obj2 = new ClassC(new ClassB());
    
    		obj1.test();
    		obj2.test();
    	}
    }

    Жоғарыда көрсетілген бағдарламаның нәтижесі:

    doSomething implementation of A
    doSomething implementation of B

    Әдістерді шақырудағы бұл икемділік мұраға қол жетімді емес, бұл композиция таңдауына тағы бір артықшылық қосады.

  4. Бірлік сынағы композициямен оңайырақ, өйткені біз суперсыныптағы барлық әдістерді қолданып жатқанымызды білеміз және оларды сынақ үшін көшіре аламыз. Ал мұрагерлікте біз суперклассқа көбірек тәуелдіміз және суперкласстың қолданылатын барлық әдістерін білмейміз. Сондықтан біз суперкласстың барлық әдістерін тексеруіміз керек, бұл мұраға байланысты қосымша жұмыс.

    Ең дұрысы, біз тек ішкі сынып пен суперсынып қатынасы «болған» ретінде анықталған кезде ғана мұраны пайдалануымыз керек. Барлық басқа жағдайларда композицияны пайдалану ұсынылады.

Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION