Obiekty, metody, typy.

0

Nigdzie nie znalazłem potwierdzenia moich wysuniętych wniosków, które opisze niżej. Ale wydaje mi się ze po przeczytaniu troche książki i przemyśleniu jednak moje zrozumienie jest dobre.

Tworzymy obiekt:

Abc x = new Abc

mamy utworzony obiekt.
Moje przemyślenia:
Obiekt zawiera jakieś dane powstałe w wyniku konstruktora klasy Abc i nic więcej.
Do zmiennej x została przypisana referencja (adres do obiektu) i typ Abc.

__(I teraz najważniejsze) Ten typ Abc który określa zmienna referencyjną mówi nam tylko tyle że na danym obiekcie pozwoli nam wykonać tylko metody klasy ABC.
__

Mam nadzieje że dobrze myślę i jeśli tak to wystarczy napisać TAK i zamykamy temat.

(jestem przy rzutowaniu referencji w dziedziczeniu i tutaj potrzebuje potwierdzenia moich przemyśleń. Tak przynajmniej wychodzi mi z mojej analizy)

0

Wywoływać metody i odnosic sie do pól tylko tej klasy, tak.

0

Jeśli pamiętasz, że obiekt posiada też wszystkie metody i pola klas nadrzędnych, a nie tylko te jawnie zdefiniowane w deklaracji klasy, to tak.

0

Shalom fajnie odpowiedział. Maciej Cąderek troche mi namieszał.
A wiec wejde teraz w szczegóły. Stworzony obiekt klasy Abc też zawiera metody klasy Abc???

========
Ja to sobie wyobrażałem tak:
a) że utworzony obiekt klasy Abc zawiera tylko pola ze swoimi wartościami (czyli stan obiektu) a do typu zmiennej referencyjnej przypisywane są informacje o metodach klasy Abc i informacja jakie pola znajdują sie w obiekcie .
b) typ zmiennej referencyjnej "stoii na straży" aby tylko metody klasy Abc były wywoływane na obiekcie klasy Abc oraz żeby odwołania do pól obiektu dotyczyły się tylko pól klasy Abc.

Takie było moje wyobrażenie. Ale może ktoś wyjaśni jak jest naprawdę??

2

Jest inaczej:

  • nawet jeżeli stworzysz 14567 obiektów klasy Abc, to istnieje tylko jeden egzemplarz każdej metody,
  • jak napisał @Maciej Cąderek, na obiekcie klasy Abc możesz wywołać metody wszystkich klas, po których ona dziedziczy (bezpośrednio lub pośrednio), W szczególności możesz wywołać metody clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait.
0

bogdans i inni zapomnijcie o dziedziczeniu, to było napisane w nawiasie i nie pytam nic o dziedziczenie.
Ogólnie pytam o obiekty i typy.
Przeczytaj jeszcze raz ze zrozumieniem moje pytania z posta #1 i #4 o co mi w nich chodzi, w szczególności na pytanie z posta #4 bo na #1 Shalom dał odpowiedź i postaraj sie na to dokładnie odpowiedzieć bez mieszania czegokolwiek innego. Pozdro.

1

W poście #4 napisałeś

aby tylko metody klasy Abc były wywoływane na obiekcie klasy Abc
A ja Ci napisałem, że to jest nieprawda. Być może nie wiesz, że w Javie każda klasa po czymś dziedziczy. Poniższy kod jest poprawny.

public class Abc
{
}
public class TestAbc
{
    public static void main(String[] args)
    {
         Abc abc = new Abc();
         System.out.println(abc.hashCode());
         System.out.println(abc.toString());
    }
}

Twoja nieumiejętność rozumienia prostych zdań jest przerażająca.

0

A ja mówiłem żebyś zapomniał o dziedziczeniu nie o to pytam. Dobrze jak sobie cos tam każda klasa dziedziczy to w pewnym sensie jest to tak jakby juz jej metoda, pola.

Proszę Cię nie wybiegaj zawsze z czymś innym, jeśli o cos pytam to odpowiedź na to tylko. Fajnie że masz dużą wiedzę na ten temat ja sobie pomału jakoś dalej pomału dojdę. Przez mieszanie wszystkiego naraz zamiast żebym zrozumiał to tylko robisz zamieszanie a potem mówisz że nie rozumiem zdań. Nie rozumiem bo jak zrobisz mix wiadomości z wiadomościami którymi jeszcze nie znam wtedy wychodzą głupie pytania. Ty tez jak sie uczyłeś robiłeś to pewnymi krokami a nie wszystko naraz, bo byś nic z tego nie rozumiał. Właśnie przez takie twoje mieszanie nie rozumiem co ty piszesz.

I teraz Cie znowu proszę zapomnij o dziedziczeniu i wyobraź sobie że klasa Abc jest klasą bazową z polami i metodami, po niczym nic nie dziedziczy. I z takimi założeniami odpowiedz na moje pytanie z posta #4.

0

W Javie nie ma sytuacji, że klasa po niczym nie dziedziczy.

0

Kiedyś kiedyś musiało tak byc jak ktoś pisał pierwsze klasy, równie ja moge napisac jaka nową klase. Ogólnie nie ważne weź tylko takie założenie i odpowiedz.

0

Dobra ja już wiem wszystko pewien kolega z forum udzielił mi przez gg poprawna informacje.

0
golec2604 napisał(a):

Dobra ja już wiem wszystko pewien kolega z forum udzielił mi przez gg poprawna informacje.

To może podziel się tą zacną informacją z innymi? Po to jest forum, a ort! ktoś będzie szukał podobnych informacji i wtedy może znajdzie ten temat a nie będzie smarował nowego a tak myślisz tylko o sobie.

0
bogdans napisał(a):

W szczególności możesz wywołać metody clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait.

bogdans wytłumacz czemu te metody są szczególne???

3

Nie mogę tego wytłumaczyć, musiałbym użyć zakazanego słowa dziedziczenie.

0
golec2604 napisał(a):

(I teraz najważniejsze) Ten typ Abc który określa zmienna referencyjną mówi nam tylko tyle że na danym obiekcie pozwoli nam wykonać tylko metody klasy ABC.

UWAGA. Podaję hasło odpowiedź:

Źle myślisz. Na danym obiekcie możesz wywoływać także inne metody, niekoniecznie jawnie zdefiniowane w klasie. Tak sformułowanej odpowiedzi oczekiwałeś? Czy to wystarczy żebyś już więcej nie negował tak istotnego pojęcia jakim jest dziedziczenie?

0

Semantycznie działa to tak, że jak masz referencję typu X, to możesz dobrać się do metod i pól udostępnianych przez typ X, nawet jeśli np obiekt ma więcej metod i pól, bo jego klasa dziedziczy po X i go rozszerza.

Jeśli chcesz zobaczyć na możliwą implementację to zobacz tutaj: https://en.wikipedia.org/wiki/Virtual_method_table

W ogólności sprawa jest taka:
Referencja na obiekt to pod spodem (tzn jest zaimplementowana jako) wskaźnik na początek obiektu (początek w sensie początek reprezentacji jako struktury w pamięci). Obiekty w Javie posiadają kilkubajtowy narzut/ nagłówek. W tym nagłówku jest wskaźnik do (bądź identyfikator) klasy danego obiektu. Do tej klasy można się dobrać wykonując metodę getClass() na dowolnym obiekcie. Klasa zawiera vtable, która to znowu zawiera wskaźniki do implementacji metod obiektu. Sam obiekt oprócz referencji do swojej klasy i małego ekstra narzutu (w Javie narzut na jeden obiekt wynosi 8 bajtów, a ZTCP to na identyfikator klasy wychodzi 4 bajty, więc kolejne 4 bajty też do czegoś są) zawiera tylko miejsce na pola (bo metody są w klasie i nie ma sensu ich duplikować w kółko, bo są zawsze stałe dla obiektu danej klasy).

0

Wibowit dość zakręcony jest ten twój opis obiektu, trudno mi jest to sobie wyobrazić. Może narysujesz i wstawisz na forum obrazek pokazujący jak wygląda obiekt?? (Ja mam bardziej pamięć do obrazów niż do opisów, jak cos widze narysowane łatwiej mi to zapamiętać niż wyobrazić to sobie z opisu)

I jedna prośba nie używajmy terminów z innych jezyków programowania. W javie są referencje a nie wskaźniki. Trzymajmy sie terminologii języka Java bo o nim jest temat.

2

Moje wyobrażenie o zawartości obiektów i klas na poziomie implementacji opiszę w tym poście. Niekoniecznie jest to w 100% zgodne z rzeczywistością.

Załóżmy, że jest taki kod:

class A {
  int i;
  int a;
}

abstract class B extends A {
  int m() {
    return 1;
  }

  public abstract char n();

  int i;
  int b;
}

interface D {
  char n();
  float o();
}

class C extends B implements D {
  char n() {
    return 'c';
  }

  float o() {
    return 3.14f;
  }

  int i;
  int c;
}

Po stworzeniu obiektu za pomocą new C() dostajemy obiekt o następujących 4-bajtowych elementach:

  • wskaźnik do klasy/ identyfikator klasy/ cokolwiek prowadzące do klasy - załóżmy, że to wskaźnik do klasy,
  • zmienna pomocnicza (tak mi wychodzi z obliczeń - narzut na obiekt to 8 bajtów nawet w 32-bitowej Javie, więc to musi gdzieś tutaj siedzieć),
  • zmienna i pochodząca z klasy A,
  • zmienna a pochodząca z klasy A,
  • zmienna i pochodząca z klasy B,
  • zmienna b pochodząca z klasy B,
  • zmienna i pochodząca z klasy C,
  • zmienna c pochodząca z klasy C,

Klasa C zawiera vtable w czterech wersjach:

  • wersja dla klasy A, która jest pusta, bo w A nie ma metod,
  • wersja dla klasy B zawierające dwa elementy:
    -- metoda m prowadząca do implementacji z klasy B,
    -- metoda n prowadząca do implementacji z klasy C,
  • wersja dla klasy C zawierająca trzy elementy:
    -- metoda m prowadząca do implementacji z klasy B,
    -- metoda n prowadząca do implementacji z klasy C,
    -- metoda o prowadząca do implementacji z klasy C,
  • wersja dla interfejsu D zawierająca dwa elementy:
    -- metoda n prowadząca do implementacji z klasy C,
    -- metoda o prowadząca do implementacji z klasy C,

Wskaźniki do metod zawsze prowadzą do klasy najniżej w hierarchii, w której jest zdefiniowana czy nadpisana dana metoda. Tak działają metody wirtualne, które są podstawą dziedziczenia w Javie. Stąd od typu zmiennej referencyjnej zależy to do którego vtable się dobieramy, ale każdy vtable ma te same wskaźniki dla tych samych metod.

Hierarchia powyżej w rzeczywistości jest błędna, bo pomija istnienie klasy Object i to, że każdy obiekt z niej dziedziczy. Z tego powodu vtable dla klasy A powinno zawierać wszystkie metody z klasy Object i analogicznie dla reszty vtable.

Dobieranie się do pól obiektu wykonuje się bezpośrednio, z pominięciem vtable. Jeżeli zdefiniujemy zmienną o tej samej nazwie na kilku poziomach dziedziczenia to nasz obiekt będzie zawierał tę zmienną w kilku kopiach i to do której kopii się odwołamy będzie zależeć od typu zmiennej referencyjnej, którą wykorzystujemy do operowania na obiekcie. Przykład: http://ideone.com/p9sdzK

Update:
Jeszcze jedna sprawa. W Javie alokowanie pamięci dla obiektu oraz wywołanie konstruktora to dwie osobne instrukcje na poziomie bajtkodu. Alokowanie pamięci dla obiektu jest połączone z czyszczeniem tejże pamięci czyli ustawianiem wartości pól na wartości domyślne (czyli int to 0, boolean to false, obiekty to null itd). Dopiero po pełnym zaalokowaniu i wyczyszczeniu wywoływany jest konstruktor.

Ponadto konstruktory są efektywnie wywoływane od najwyższego (czyli z klasy Object) do najniższego (czyli tego który podajemy po słówku new). Działa to tak, że pierwszą instrukcją w kodzie Javowym konstruktora (lub jedną z pierwszych na poziomie bajtkodu) jest wywołanie super() czyli konstruktora z klasy nadrzędnej. Wywołanie to jest robione explicite (poprzez wpisanie tego super(cośtam) do konstruktora) lub implicite (czyli jak kompilator nie znajdzie super() w konstruktorze to sobie sam dopisze). Ale w sumie kolejność inicjalizacji to osobny temat, więc możesz to tutaj olać.

0

Ło matko !!!

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