• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Kompozycja - pola publiczne i prywatne

Object Storage Arubacloud
+2 głosów
2,700 wizyt
pytanie zadane 8 kwietnia 2017 w Java przez itcloud Gaduła (3,380 p.)

Czytam sobie "Thinking in Java"  wyd. IV (polska edycja) str. 225 "Wybór między kompozycją a dziedziczeniem" i nie rozumiem tych zapisów poniżej:

Kompozycja jest zazwyczaj stosowana wtedy, gdy potrzebne są właściwości istniejącej klasy wewnątrz własnej, lecz nie jej interfejs. Osada się zatem obiekt tak, by można go było wykorzystać w tworzonej klasie, ale użytkownik klasy widzi tylko interfejs nowej klasy bez interfejsu obiektu osadzonego. Aby uzyskać taki efekt, wystarczy zamieścić obiekty klas istniejących wewnątrz nowej klasy jako składowe typu private.

Dotąd myślałem, że zrozumiałem czym jest interfejs,ale jak czytam to powyższe to wiem, że nic nie wiem :/

Interfejs który implementuje dana klasa to po prostu dopisywania konkretnych ciał metod z danego interfejsu w klasie, która ten interfejs implementuje. Gdzie więc przy kompozycji ten interfejs nowej klasy? O co tu chodzi??

Druga kwestia, założmy, że mam klasę (a w zasadzie dwie klasy i testującą) w której jest obiekt innej klasy:

package kompozycja2;

public class Main {

	public static void main(String[] args) {
		
		KlasaA a1 = new KlasaA();
		System.out.println(a1.getPoleA());
		
		KlasaA a3 = new KlasaA();
		a3.setPoleA(666);
		
		KlasaB b1 = new KlasaB(a3);

	}
}



package kompozycja2;

public class KlasaB {
	//tutaj jest ten przykład kompozycji, tak?
	private KlasaA a2;
	
	KlasaB(KlasaA a2){
		
		System.out.println("Konstruktor klasaB");
		this.a2 = a2;
		System.out.println("Inicjalizacja obiektu a2 typu KlasaA");
	}
	
	public KlasaA getA2() {
		return a2;
	}

	public void setA2(KlasaA a2) {
		this.a2 = a2;
	}
	
}


package kompozycja2;

public class Main {

	public static void main(String[] args) {
		
		
		KlasaA a1 = new KlasaA();
		System.out.println(a1.getPoleA());
		
		KlasaA a3 = new KlasaA();
		a3.setPoleA(666);
		
		KlasaB b1 = new KlasaB(a3);
                //i co dalej, jak zobaczyc roznice gdy w klasaB pole z obiektem klasaA będzie publiczne a nie prywatne.. 
               //jak przetestować fatk, że pole w KlasaA ma nową wartość 666 i teraz ta wartość jest dostępna z poziomu klasaB..


	}

}

Wydaje mi się, że z powodu braku praktyki nie rozumiem np. powyższego przykładu, który próbuję skończyć a nie jestem w stanie. Chodzi o te końcowe komentarze. No bo tak : tworzę sobie nowy obiekt a3 typu KlasaA. Przekazuję go w konstruktorze do KlasaB(), no i jak teraz odczytać tę wartosć pola typu KlasaA z poziomu już klasaB? Proszę o pomoc.

1 odpowiedź

+1 głos
odpowiedź 8 kwietnia 2017 przez Mateusz51 Nałogowiec (28,180 p.)
W cytacie który przytoczyłeś chodzi o to że dziedziczenie powoduje rozszerzenie interfejsu klasy rozumianego w sensie zbiór publicznych metod jaka ta klasa daje na zewnątrz. W kompozycji chodzi o to że możesz rozszerzyć działanie klasy o dodatkowe funkcie  bez dodawania do klasy dodatkowych metod publicznych które oferuje klasa z której składasz kompozycje.
komentarz 8 kwietnia 2017 przez itcloud Gaduła (3,380 p.)
Czy da się to odnieść do mojego przykładu z kodem?

A w tym cytacie inferejs to nie "interface" tylko jak to określiłeś a ja nieco to zmienię, cała "motoryka" klasy? Czyli funkcje które oferuje? W dziedziczeniu te funkcje się "pobiera" od klasy nadrzędnej.. a w kompozycji.. jeszcze prościej możesz napisać? Bo na moje w moim przykładzie widać, że jednak jeśli daję do składowych klasy inną klasę (jej obiekt), to defacto korzystam z tej funkcjonalności klasy, której obiekt mam do dyspozycji.
3
komentarz 8 kwietnia 2017 przez Mateusz51 Nałogowiec (28,180 p.)

Kompozycja to poprostu używanie klas wewnatrz innych klas bez dziedziczenia po nich. Tak jak samochód jest kompozycja kół, silnika, kierownicy. A nie dziedziczy po kołach, silnik i tak dalej. Z punktu widzienia użytkownika on chce jechać do przodu, skrecać. A nie krecić się, czy zapalać paliwo.

class Cos{
private Logger logger;

public printSomething(String something){
 logger.log(something); // wykorzystuje logger do swoich celów ale z ptk uzytkownika on nie musi nawet wiedzieć że on istnieje
 System.out.println(something);
}

}

 

1
komentarz 9 kwietnia 2017 przez ShiroUmizake Nałogowiec (46,300 p.)
Interfejs służy po to by ułatwić sobie życie np: jak obieky domeny aplikacji są do sb bardzo podobne, ale zwracają inne wartości (Component, Action/Reaction, Strategy, Factory).

Chcemy ograniczyć dostęp do klasy do metod, które nie stanowią zagrożenia stabilności aplikacji (czy to użytkownik, dev etc...) . Inaczej chcemy dać ograniczony dostęp do funkcjonalności (np: GUI - interesuje mnie gotowy projekt, nie interesuje mnie jak to jest zbudowane, jak wygląda komunikacja (między klasami pośredniczącymi, a potrzebują dostęp (Core Applikacji).
komentarz 9 kwietnia 2017 przez itcloud Gaduła (3,380 p.)
Możesz jaśniej? Co to znaczy że ułatwiamy sobie życie interfejsami? Masz na myśli to, że jest np. obiekt A i B, każdy ma taką samą metodę w środku (o takiej samej nazwie) bo są oparte na tym samym interfejsie (szkielecie) a każdy jednak robi to samo w nieco inny sposób ? (tak jak analogia do klas sortujących)? Myli mi się cały czas klasa z interfejsem. Tzn. wiem że klasa ma w sobie konkretne implementacje, a interfejsy są tylko takimi "szkicami". Ale równie dobrze mógłbym po prostu sobie ustalić z programistami w zespole, że jak robisz wyświetlenie treści, to metoda w klasie ma się nazywać View, po co tutaj ten interfejs? Dziedziczenie - rozumiem, nie trzeba powielać kodu. A interfejs? Czy zawsze w paktyce będzie on występować po "lewej stronie" inicjalizacji obiektu, np. ?

List<..> lista = new ArrayList<...>();  

//czyli że na lewo jest typ interfejsowy, a po prawej zawsze jakaś klasa, czyli klasa która musi IMPLEMENTOWAĆ czyli mieć wszystkie metody tego interfejsu?

Czy o to tu chodzi w PRAKTYCE, co napisałem wyżej? Jeśli tak, czemu nikt do diaska nie potrafi tak tego opisać laikowi ???

A ten drugi akapit to o kompozycji ?
1
komentarz 9 kwietnia 2017 przez ShiroUmizake Nałogowiec (46,300 p.)

A co jeżeli twój zespół ma 50 programistów, a kod ma powiedzmy 2000 klas dalej będziecie się umawiać ;). Inny przykład tymrazem Webowy: Dziwnych powodów piszesz w JAVAEE  masz 10 typów użytkowników każdy ma 20 zasad dostępu, tworzysz nowy typ użytkownika i nagle zapomniałeś której funkcjonalności (Założmy , że testów nie pisałęś (na testach by wyszło) i wrzuciłeś do produkcji. Po miesiącu krzyczy ktoś na cb, że klasę którą zaimplementowałeś wyrzuca nullPointException (a to jest bardzo ciężko znależć), a ty już zapomniałeś (i nie napisałeś testów)  gdzie to robiłeś i zaczyna zabawa testów od zera. System nie działa.

 

Co to znaczy że ułatwiamy sobie życie interfejsami? 

 

Mamy taki interface iComponentMoster 

public interface iComponentMonster {
public int getPoinstattack();
public int getPointDefend();

}

I mamy klase pinkMonster, yellowMonster itd... 

public class pinkMonster implements iMonSterComponent;

public int getPointAttack (){

return 50;
}

public class yellowMonster implements iMonsterComponent{

public int getDefendPoints(){
return 30;

}
}

Dzięki temu mogę łatwo tworzyć kolejne implementacje potwora, gdyż mam gotowy zestaw metod, która dana klasa musi interpretować. 2. Dzięki iMonsterComponent mogę bardzo łatwy sposób tworzyć kolejne interfejsy i wyspecyfikować mojego potwora.

Zadam ci głupie pytania a czy interfejs ma konstruktora :)?

Który akapit?

1
komentarz 9 kwietnia 2017 przez Mateusz51 Nałogowiec (28,180 p.)
Generalnie interfejs to jest własnie takie dogadanie się programistów. Tylko musisz wziąć pod uwage że czesto programisci nie znaja sie w żaden sposób. Np programisci jądra javy tworząc swoją bilioteke standardową poprzez interfejsy umawiaja się że jak jakiś obiekt ma zaimplementowany interface np comparable to można go porównywać.

Czesto w praktyce tak się robi, ale nie zawsze. Nim bardziej skąplikowany system tym czesciej odwołujesz się poprzez interface bo łatwiej jest wymienic kawałki kodu. W prostych programach nie ma czesto poptrzeby tworzenia i implementowania wlasnych interfejsów.
komentarz 9 kwietnia 2017 przez itcloud Gaduła (3,380 p.)
No nie, konstruktor ma jedynie klasa. Ale chyba nie załapałem Twojego przykładu, bo interfejs nieco inaczej się nazywa, a implementujesz już inną nazwę:

implements iMonSterComponent

Implementujesz po jednej metodzie, a nie dwie. To taki "skrót myślowy" ?

Drugi akapit, to to: " Chcemy ograniczyć dostęp do klasy do metod... "

Ale generalnie dobrze łapię tą różnicę pomiędzy interfejsem a klasą? Chodzi mi o praktyczne stosowanie tego, często widzę w kodach źródłowych, że jako argument do klasy (do jej konstruktora) przekazywany jest właśnie interfejs.
komentarz 9 kwietnia 2017 przez ShiroUmizake Nałogowiec (46,300 p.)

Sorki, wrzucę ci przykładowy kod.

public class LoginAccessControler extends AccessControler implements iAccessControler {
    private HttpServletResponse response;
    public void doAccess() {
        decideWhatIdo();
    }
 
   public void decideWhatIdo(){
         iRegisterUser user = (iRegisterUser) super.getSession().getAttribute("user");
        if (!super.isRegisterUser()){
            iAction action = new AccessAction();
            super.setAction(action);
        }
         else if (!user.getAccessRules().isAccessLoginPage()  && user.isIsLogged()){
             iAction action = new SendRedirectProfileAction(); 
             action.doAction(response);
        }
         
        else if (user.getAccessRules().isAccessLoginPage() && !user.isIsLogged()){
           iAction action = new AccessAction();
           action.doAction(response);
        }
        else if (!user.getAccessRules().isAccessLoginPage() && !user.isIsLogged()){
           iAction action = new AccessAction ();
           action.doAction(response);
        }
       
    }
    

    @Override
    public void setResponse(HttpServletResponse response) {
        this.response = response;
        super.setResponse(response);
    }

    @Override
    public void setRequest(HttpServletRequest request) {
        super.setRequest(request);
    }
    
   
    
}

W skrócie jest tu użyty wzorzec Strategi, do decydowania co z danym userem(typem) robimy w kontekście przyjęcia żądania z filtra. Implementuje interfejs iAccessControler który nie mówi mi jak ja to zrobię, ale co dana klasa (jej szersza interpretacja) ma za metody, moim zadaniem jest najwyżej napisanie implementacji.

Dla potwierdzenia słów możesz sobie wejść tutaj:

https://github.com/PatrykMaternicki/dev_HazeBankCreditSystem/tree/master/src/main/java/com/Controlers/accessControler

Każdy z tych kontrolerów przyjmuje ten interfejs.

Wiem, że accessControler musi podjąc jakąś decyzje, ale tych decyzji może być sporo, dlatego tworzę odwołanie się do interfejsu (typ ogólny) i przepisuje mu co ma zrobić. Gdybym nie użył interfejsu musiałbym stworzyć dokładny typ akcji. Druga zaleta, poziomu accessControler nie obchodzi go jak to jest zrobione (Jego zadanie jest proste, ma zdecydować co się dzieje), akcja ma się wykonać, ale nie za bardzo go obchodzi jak się wykonać. 

Przejdżmy do pakietu domain.accessSystemApplication.Action

https://github.com/PatrykMaternicki/dev_HazeBankCreditSystem/tree/master/src/main/java/com/domain/AccessSystemApplication/Action

Wejdżmy do akcji np: sendRiderctProfileAction

package com.domain.AccessSystemApplication.Action;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SendRedirectProfileAction implements iAction {

    @Override
    public void doAction(HttpServletResponse response) {
        try {
            response.sendRedirect("profile");
        } catch (IOException ex) {
            Logger.getLogger(SendRedirectProfileAction.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

   
    
}

Ta akcja wykonuje zmianę kierunku żądania na filter profile i tu zaczyna znowu zabawa czy ona ma prawa etc.

Dzięki zastowaniu interfejsu, wiem że akcja musi się wykonać. Interfejs pozwala mi na szybkie tworzenie małego kodu, którego zadaniem jest wykonanie jednego zadania oraz rozdzielnia zależności zadań.

(Controler decyduje , action wykonuje)

Chcemy ograniczyć dostęp do klasy do metod...

Powiedzmy mamy jakiś core applikacji (nie będzie jakiś GUI), i on odwołuje się powiedzmy buttonBuilder ale nie po przez interfejs. I mamy jakiś PDFBuilder który się odwołuje się po przez interfejs buttonBuilder.

Dlaczego?

Jak startuje core, GUI musisz dostarczyć wszystkie parametry do budowy komponentów. PDFBuilder jedynie odwołuje się do gotowych komponentów (Builder zwraca jakieś gotowe obiekty), gdyż sam nie ma metod (i nie powinen mieć) dostarczająych parametry do budowych tych obiektów. 

Co do iRegisterUser itd... możesz spotkać interfejsy których się nie da jasno określić co one robią (mają dużo metod) , ale też możesz spotkać takie które jasno określają co się ma dziać np: equalable (klasa musi cos porownac), viewable (klasa musi przekladac zadanie na widok) albo agresiveable (klasa potwor jest agresywna).

Wszystko zależy od twoich potrzeb, implementalności interfejsów wielu klasach.

 

 

Podobne pytania

0 głosów
1 odpowiedź 1,597 wizyt
pytanie zadane 15 listopada 2017 w Sieci komputerowe, internet przez Krzysztof Ciborowski Użytkownik (510 p.)
0 głosów
1 odpowiedź 623 wizyt
pytanie zadane 18 lipca 2021 w Rozwój zawodowy, nauka, praca przez programer Obywatel (1,190 p.)
0 głosów
2 odpowiedzi 197 wizyt
pytanie zadane 21 listopada 2020 w Offtop przez mattzaq Nowicjusz (200 p.)

92,573 zapytań

141,423 odpowiedzi

319,648 komentarzy

61,959 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...