Odwołanie się do innej klasy

Odpowiedz Nowy wątek
2011-10-18 19:58
0

Witam ponownie. Mam klasę Tablica, której kawałek kodu wygląda tak:

public class Tablica
{
    //Pola prywatne
    private int [] tablica = new int[100]; //tablica pamietajaca do 100 liczb calkowitych
    private int liczbaElementow = 0; //liczba aktualnie pamietanych elementow

    //Konstruktory
    public Tablica(int[] tablica) //konstruktor przyjmujacy tablice liczb calkowitych
    {liczbaElementow=0;}

    public Tablica(Tablica tablica) //konstruktor przyjmujacy obiekt tablica typu Tablica
    {liczbaElementow=0;}

(...)

}

Ogólnie posiada ona:

a. Dwa pola prywatne – tablicę oraz liczbę aktualnie zapisanych w niej elementów.
b. Konstruktory:
-przyjmujący tablicę liczb całkowitych
-przyjmujący obiekt typu Tablica
c. Metody pobierzTablice(), pobierzLiczbeElementów() zwracające odpowiednie
d. Metodę dodaj(int x) dodającą element na koniec tablicy
e. Metodę dodajNaK(int x, int k) dodającą element na pozycję k w tablicy
f. Metodę usun() usuwającą ostatni element tablicy
g. Metodę usunZK(int k) usuwającą element z pozycji k w tablicy
h. Metodę suma() sumującą wartości elementów tablicy
i. Metodę maksymalnyEl() znajdującą wartość maksymalna w tablicy
j. Metodę czyJestX(int x, int k) sprawdzającą czy podana wartość x występuje na którejś z k początkowych pozycji tablicy
k. Metodę roznowartosciowa() sprawdzającą czy tablica jest różnowartościowa
l. Metodę tworzenieRoznowartosciowej() która eliminuje wszystkie powtórzenia elementów tablicy
m. Metodę sortuj() która uporządkuje rosnąco elementy tablicy (wykorzystaj dowolny algorytm sortowania)
n. Metodę toString() wyświetlającą tablicę na konsoli

i teraz mam takie polecenie (a raczej jego część):

  1. Zdefiniuj klasę TablicaUporządkowana (rosnąco). Klasa zawiera:
    a. Dwa pola prywatne – tablicę oraz liczbę aktualnie zapisanych w niej elementów.
    b. Konstruktory
    • przyjmujący tablicę liczb całkowitych
    • przyjmujący obiekt typu Tablica
    • przyjmujący obiekt typu TablicaUporządkowana

Jak zdefiniować taką klasę (te pola prywatne + konstruktory)? Pole prywate dot. liczby aktualnie zapisanych elementów to nie problem, gorzej z resztą. Domyślam się, że muszę się w niej odwołać jakoś do klasy Tablica, żeby napisać konstruktor przyjmujący obiekt typu Tablica. No i domyślam się, że muszę wykorzystać metodę sortuj() z klasy Tablica do posortowania obiektu tablica typu Tablica, żeby posortować tamtą tablicę, a potem przypisać ją temu obiektowi typu TablicaUporządkowana (załóżmy, że to będzie np. tablica2). Jednak znów pytanie - jak wywołać tamtą metodę sortuj() z klasy Tablica z poziomu klasy TablicaUporządkowana, a następnie jak przypisać obiektowi tablica2 obiekt tablica?

Dzięki z góry za pomoc

Pozostało 580 znaków

2011-10-19 21:48

Najleniwsze możliwe rozwiązanie, to użycie dziedziczenia. TablicaUporządkowana jest wtedy również typu Tablica, więc żadnych wymyślnych konwersji w tę stronę nie trzeba wymyślać. Natomiast każdy przeciążony konstruktor (te same parametry, co u rodzica) i każdą metodę z klasy Tablica (która powiększa zawartość tablicy) należy przedefiniować w klasie TablicaUporządkowana w taki sposób aby wywołać oryginalną metodę poprzedzoną przez "super.", a następnie wywołać metodę sortuj(), aby znowu uzyskać tablicę uporządkowaną. Przy usuwaniu nie jest to potrzebne ponieważ porządek nie zmieni się. Przykład:

//Rozwiązanie typu bezczelny i leniwy student
//Pola są zdefiniowane w klasie rodzica mimo, że są niedostępne
public class TablicaUporządkowana extends Tablica
{
    public TablicaUporządkowana(int[] tablica)
    {
        super(tablica);
        sortuj(); //użyje wersji rodzica lub przedefiniowaną tutaj
    }

    public TablicaUporządkowana(Tablica tablica)
    {
        super(tablica);
        sortuj(); //użyje wersji rodzica lub przedefiniowaną tutaj
    }

    public TablicaUporządkowana(TablicaUporządkowana tablica)
    {   //już posortowana
        super(tablica);
        //...
    }

    @Override public void dodaj(int x)
    {
        super.dodaj(x);
        sortuj();
    }

    @Override public void dodajNaK(int x, int k)
    {
        super.dodajNaK(x, k);
        sortuj();
    }
} //finito

//Rozwiązanie typu grzeczny i pracowity student (ale badziewny kod)
class TablicaUporządkowana2
{
    private int[] tablica = new int[100];
    private int liczbaElementow = 0;

    public TablicaUporządkowana2(int[] tablica)
    {
        Tablica t = new Tablica(tablica);
        t.sortuj(); //użyje wersji rodzica lub przedefiniowaną tutaj
        this.tablica = t.pobierzTablice();
        this.liczbaElementow = t.pobierzLiczbeElementów();
    }

    public TablicaUporządkowana2(Tablica tablica)
    {
        this(tablica.pobierzTablice());
    }

    public TablicaUporządkowana2(TablicaUporządkowana2 tablica)
    {
        this.tablica = tablica.pobierzTablice();
        this.liczbaElementow = tablica.pobierzLiczbeElementów();
    }

    //...
    //wszystkie metody powielone Ctrl+C, Ctrl+V z klasy Tablica plus dodatkowe sortowanie
}

Jeżeli ktoś komuś coś, ewentualnie nikt nikomu nic, to właściwie po co...?
edytowany 2x, ostatnio: Olamagato, 2011-10-20 08:19

Pozostało 580 znaków

2011-10-20 00:43
0

Sprawdzę to i dam znać ;) Dzięki za pomoc!

Dzięki wielkie. Sprawdziłem i ten pierwszy kod zdecydowanie lepiej wygląda moim zdaniem, ale żeby się facet nie czepiał użyję drugiego. Natomiast pytanko mam takie odnośnie tego co pogrubiłem poniżej:

Olamagato napisał(a)

public TablicaUporządkowana2(TablicaUporządkowana2 tablica)
{
this.tablica = tablica.pobierzTablice();
this.liczbaElementow = tablica.pobierzLiczbeElementów();

}

//...
//wszystkie metody powielone Ctrl+C, Ctrl+V z klasy Tablica plus dodatkowe sortowanie
}

To nie przejdzie niestety, bo tablica jest tu klasy TablicaUporządkowana2, nie Tablica, a więc nie użyję metod pobierzTablice() i pobierzLiczbeElementow() z klasy Tablica. Jak metody te dwie przekopiuje do tej klasy z klasy Tablica to tez niestety nie pomoze, bo np. nie pobiore tym liczby elementow z klasy Tablica czy tez samej tablicy z tamtej klasy. Jak wiec tutaj to rozwiazac? Dzieki raz jeszcze za pomoc

Ta, bo przerabiałem klasę TablicaUporządkowana bez próby kompilacji. Oczywiście na parametrze tablica można wywołać tylko zdefiniowane w tej klasie metody klasy TablicaUporządkowana2. W tym wypadku można by pobrać dostęp bezpośrednio za pomocą pól obiektu pod referencją tablica lub zdefiniować metody pobierzTablice() i pobierzLiczbeElementów(). Dlatego właśnie rozwiązanie oparte na dziedziczeniu wydaje mi się dużo bardziej eleganckie mimo, iż formalnie nie spełnia wymogu jawnego zdefiniowania pól. - Olamagato 2011-10-20 20:34

Pozostało 580 znaków

2011-10-20 21:38
1

Rozwiązanie z dziedziczeniem można jeszcze znacznie uprościć, wykorzystując fakt, że TablicaUporządkowana jest zawsze uporządkowana i że dodaj(x) = dodajNaK(x, liczbaElementow):

public class TablicaUporządkowana extends Tablica {
    public TablicaUporządkowana(int[] array) {
        super(array);
        super.sortuj();
    }

    public TablicaUporządkowana(Tablica tablica) {
        super(tablica);

        if (!(tablica instanceof TablicaUporządkowana)) {
            super.sortuj();
        }
    }

    @Override
    public void dodaj(int x) {
        dodajNaK(x, 0);

        // to wymaga sortowania:
        // super.dodaj(x);
        // super.sortuj();
    }

    @Override
    public void dodajNaK(int x, int k) {
        k = Arrays.binarySearch(pobierzTablice(), 0, pobierzLiczbeElementów(), x);
        super.dodajNaK(x, (k < 0) ? ~k : k);
    }

    @Override
    public void sortuj() {
        /* zawsze posortowana */
    }
}

To cały potrzebny kod.

edytowany 9x, ostatnio: iooi, 2011-10-22 11:50
Pokaż pozostałe 3 komentarze
Dobra, już widzę. Ale mniejsza z tym. - iooi 2011-10-21 14:00
Jedyne na czym można oprzeć budowę klasy pochodnej jest interfejs publiczny i chroniony klasy bazowej. Żadnych innych założeń nie powinno się robić. Z kolei do właściciela klasy bazowej należy utrzymanie tego samego sensu interfejsu, który wcześniej udostępnił. Pewnie, że wersje domyślne pewnych metod zwykle wywołują wersje ogólniejsze z konkretnymi argumentami, ale jest to szczegół zarezerwowany tylko dla twórcy klasy. A on nie musi go wcale utrzymać. - Olamagato 2011-10-22 02:29
Proponujesz więc reimplementację wszystkich takich metod na dokładnie to samo? Zauważ, że po dokonaniu jakiejkolwiek zmiany w klasie bazowej, klasa pochodna w tym przypadku już będzie miała złą implementację == to co pisałem poprzednio. - iooi 2011-10-22 11:20
Problem wynika tylko z tego, że TablicaUporządkowana nie powinna dziedziczyć po Tablica w takiej formie - nie powinna mieć nawet metody dodajNaK. Chociaż rozumiem twoje podejście, rozwinąłem trochę kod. - iooi 2011-10-22 11:44
Tutaj najlepsza byłaby prosta delegacja, którą wykluczyłem z powodu jawnego nakazu zdefiniowania w Tablicy uporządkowanej pól prywatnych dla tablicy i pola. Byłoby więc powielenie danych i utrzymywanie synchronizacji. Gdyby tego dziwnego nakazu nie było, to problem by nie istniał. - Olamagato 2011-10-22 15:20

Pozostało 580 znaków

2011-10-20 22:02
0

Dzieki wielkie za odpowiedzi! Juz chyba sobie poradze ;)

edytowany 1x, ostatnio: pawel_d, 2011-10-20 22:02

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0