[ Rapaic Rajko @ 24.09.2013. 15:39 ] @
Pozdrav svima, kao sto se iz pitanja moze naslutiti, pocetnik sam u javi i istrazujem je/poredim sa drugim jezicima.

Od starta sam primetio odsustvo sluzbene reci "virtual", i iz odradjenih primera sam shvatio da su u javi SVE funkcije virtuelne. Pretpostavljam da je to namerno :) , i pitam: postoji li nacin da se deklarise non-virtual funkcija? Drugim recima, moze li da se natera jedan te isti objekat da, prostim cast-ovanjem u super klasu, drugacije odradjuje pozvanu (nasledjenu pa pregazenu) metodu?

Pozz

P.S. U jezicima koji imaju keyword "virtual", postojanje non-virtual metoda omogucava specificne tehnike dizajna klasa.
[ dejanet @ 24.09.2013. 17:07 ] @
U javi bi trebalo koristiti keyword final za taj slucaj.
[ Rapaic Rajko @ 25.09.2013. 08:54 ] @
A ne, final (u super klasi) onemogucava pisanje iste metode ("gazenje") u subklasi. Ne mozete pregaziti final metodu ni na koji nacin.

Da objasnim drugim recima. Uz keyword "virtual" ide i "override". U jezicima koji poznaju ova dva termina, moguce je i ovako nesto:

1) Deklarisemo obicnu (non-virtual) metodu test() u super klasi SuperClass.
2) Pregazimo metodu test() u subklasi SubClass.
3) Kreiramo instancu subklase Sub1 i pozovemo metodu Sub.test(); odradice se upravo kod iz subklase.
4) Uradimo typecast instance Sub1 i pozovemo metodu test, znaci ovako ((SuperClass) Sub1).test(); odradice se kod iz super klase.

Medjutim, u javi nije tako, ako metoda uopste moze da se pregazi (nije final), onda je ona obavezno virtualna. Sto znaci da ce se po 3) i 4) iz gornjeg ogleda uvek izvrsiti kod iz subklase SubClass.

Gresim li negde? Postoji li razlog zasto je mehanizam nasledjivanja metoda u javi ovako postavljen, mozda security ili slicno..?

Pozz
[ dejanet @ 25.09.2013. 12:40 ] @
U Javi mozes da definises tkz. class method (sa keywordom static) i instance method:

public static void ClassMethod() {....}
public void InstanceMethod() {....}


Ako su metodi sa istim signature-om kao u super klasi, onda imamo relaciju:

Instance method u sub klasi -> overrides -> Instance metod u super klasi
Static method u sub klasi-> hides -> Static method u super klasi.

Dobro poznat primer:

Code:
public class Animal {
    public static void testClassMethod() {
        System.out.println("The class" + " method in Animal.");
    }
    public void testInstanceMethod() {
        System.out.println("The instance " + " method in Animal.");
    }
}


public class Cat extends Animal {
    public static void testClassMethod() {
        System.out.println("The class method" + " in Cat.");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method" + " in Cat.");
    }

    public static void main(String[] args) {
        Cat myCat = new Cat();
        Animal myAnimal = myCat;
        Animal.testClassMethod();
        myAnimal.testInstanceMethod();
    }
}



Output:

Code:
The class method in Animal.
The instance method in Cat.
[ dusans @ 25.09.2013. 13:58 ] @
Čovek pita kako da dobije baš to što si demonstrirao sa metodom KLASE.
Da li može da dobije takvo ponašanje i sa metodama instance (a ako ne, zbog čega i zašto je tako u Javi)?
[ dejanet @ 25.09.2013. 16:44 ] @
Instance method(koji ima isti signature) uvek override-uje metod iz super klase.
Medjutim metod iz super klase se moze izvrsiti uz super keyword.

Na osnovu gore primera: testInstanceMethodB

Code:
public class Animal {
    public void testInstanceMethodA() {
        System.out.println("The instance A" + " method in Animal.");
    }
    public void testInstanceMethodB() {
        System.out.println("The instance B" + " method in Animal.");
    }
}


public class Cat {
    public static void main(String[] args) {

        Animal myCat = new Animal() {

            public void testInstanceMethodA() {
                System.out.println("The instance A" + " in MyCat.");
            }

            public void testInstanceMethodB() {
                super.testInstanceMethodB();
            }

        };

        myCat.testInstanceMethodA();
        myCat.testInstanceMethodB();
    }

}


Output:

Code:
The instance A in MyCat.
The instance B method in Animal.
[ Rapaic Rajko @ 26.09.2013. 12:35 ] @
Zahvaljujem na odgovorima.
Medjutim, zadnji primer upravo pokazuje ogranicenost jave zbog ignorisanja "virtual - override" mehanizma: sta ako imam 4 super klase ("preci", sve jedan ispod drugog) i zelim da radim typecast instance po volji..?

Zakljucak je da definitivno nije moguce typecast-om pozvati nasledjenu metodu iz super klase. Ali koji je razlog, verovatno security..?

Pozz
[ dusans @ 26.09.2013. 13:07 ] @
@Rajko,

U kom jeziku je moguće raditi upcasting tako da se pozove virtuelna metoda neke od baznih klasa?
U C# kao i u Javi se uvek poziva poslednja override-ovana metoda bez obzira kako je objekat cast-ovan
i kako ga posmatramo i takvo ponasanje je verujem u svim jezicima po defaultu.
Na primer, ove 3 linije uvek daju isti rezultat:

Code:

Tiger.Say();
((Mamal)Tiger).Say();
((Animal)Tiger).Say();


E sada, u C# postoji keyword "new" koji dozvoljava da prekineš sa postojećom implementacijom metode
i da uvedeš novu implementaciju metode sa istim potpisom - redefinisanje metode.
Ovime se stara metoda iz nasleđene klase sakriva ako posmatraš objekat koji je nove klase (i nadalje)
Ako bi u prethodnom primeru radio "new" umesto "override", svaka od 3 linije bi dala različit rezultat.

Mene baš interesuje koji jezici dozvoljavaju poziv metode iz neke od baznih klasa,
znači ovo što si pitao i očigledno ne može u Javi.
I ako može neki primer koda, sintakse.

Pozdrav!
[ Nymeria @ 26.09.2013. 19:17 ] @
Probaj (C#) :)

Code (csharp):

class Program
    {
        static void Main(string[] args)
        {
            tiger t = new tiger();
            t.Say();
            ((mamal)t).Say();
            ((animal)t).Say();
            Console.ReadLine();
        }
    }

    class animal
    {
        public void Say() { Console.WriteLine("i'm animal"); }
    }
    class mamal:animal
    {
        public void Say() { Console.WriteLine("i'm mamal"); }
    }
    class tiger:mamal
    {
        public void Say() { Console.WriteLine("i'm tiger"); }
    }
 
[ Rapaic Rajko @ 26.09.2013. 20:43 ] @
@dusans: u kom jeziku? u svakom koji poseduje keywords "virtual" i "override", recimo ObjectPascal/Delphi, C++ itd. Situacija je obrnuta u odnosu na javu: ako se ne navede eksplicitno "virtual", metoda je non-virtual. Kompajler te lepo upozori da gazis/sakrivas istoimenu metodu iz bazne klase, ali na tome sve ostaje: programer valjda zna sta radi :) . Takodje te upozori i ako gazis virtuelnu metodu ne-virtualnom (izostavljena rec "override"), i opet se daje za pravo programeru ;) .

Hehe, cika Stroustrup mora da se sad smeska negde iz prikrajka... :)

Pozz

P.S. @Nymeria: nemam C# na masini, tako da ne znam sta producira gornji primer..?
[ dusans @ 26.09.2013. 21:25 ] @
@Nymeria

U tom primeru koji si dao, metode nisu virtuelne već prepisuju (sakrivaju) jedna drugu.
To je drugi slučaj koji sam pominjao u mom postu, dakle kada se ne koriste virtual/override.
new keyword ispred metoda u mamal i tiger je izostavljen (dozvoljeno je po sintaksi),
ali to ne menja suštinu da su ovo ne-virtuelne metode (koje po svemu sudeći nije moguće dobiti u Javi):



@Rajko, Output:

i'm tiger
i'm mamal
i'm animal


Na ovo sam prvenstveno mislio u mom primeru kod virtual/override metoda:
Code:

    class Program
    {
        static void Main(string[] args)
        {
            tiger t = new tiger();
            t.Say();
            ((mamal)t).Say();
            ((animal)t).Say();
            Console.ReadLine();
        }

        class animal
        {
            public virtual void Say() { Console.WriteLine("i'm animal"); }
        }
        class mamal : animal
        {
            public override void Say() { Console.WriteLine("i'm mamal"); }
        }
        class tiger : mamal
        {
            public override void Say() { Console.WriteLine("i'm tiger"); }
        }
    }

@Rajko, Output:

i'm tiger
i'm tiger
i'm tiger
[ Rapaic Rajko @ 27.09.2013. 11:46 ] @
Hvala jos jednom na iscrpnim odgovorima! :)

Ne znam kako vi, ali meni licno je ignorisanje "virtual-override" keywords veliki minus za javu. To cak narusava koncept OOP-a, rekao bih, a i opterecuje procesor (ili rasterecuje? to je ona prica sa VMT tabelama... hmmm). Programer mora imati mogucnost izbora virtual ili ne (moje misljenje, svakako).

Pozz
[ bantu @ 27.09.2013. 12:39 ] @
Mislim da nije minus i da ne ne dostaje, ta da programer ne morda da ima opciju da to bira. Dugo se bavim javom i ovo je prvi put da čujem da neko pita za ovaj mehanizam u javi. Mislim da to nema veze sa OOP već je stvar konvencije i kad bi već morao da se odlučim mislim da ga prije podupire nego narušava jer forsira uvijek jednako ponašanje. A to da opterećuje procesor, ne znam šta bih rekao na to.

Java ne poznaje ni klasične pointere kakvi postoje u C-u, pa da li nedostaju? Postoji jako mnogo programskih jezika koji imaju C-like sintaksu i osim toga ništa više. Ti biraš onaj koji ti odgovara za konkretan projekat. Mislim da si navikao na neke koncepte i obrasce programiranja, ali ako mjenjaš programski jezik moraš i koncepte programiranja i design pattern-e da prilagođavaš. Ne postoji ultimate programski jezik, već najadekvatniji za vrstu problema, platformu, itd...

I da, nije mi namjera da započinjem neku besmislenu raspravu, ovo je samo moje mišljenje.
[ blekmor @ 08.10.2013. 15:51 ] @
Nedostatak NON-virtual metoda kao takvih uopšte ne narušava koncepte OOPa. Moj stav je čak da NON-virtualne metode omogućavaju da programer naruši koncepte OOPa. Ukoliko si ti override-ovao neki metod koji je već implementiran(znaci nije metod interfejsa kojeg implementiramo , ili apstraktni metod nadklase, nego IMPLEMENTIRANI metod), to znači da treba drugačije da organizuješ klase, apstraktnije. Virtual metodi ti omogućavaju da narušiš Liskov princip substitucije. Ono što je najbitnije je da se uvjek može naći jednostavna elegantnija zamjena za NON-virtualne metode.




[Ovu poruku je menjao blekmor dana 09.10.2013. u 19:46 GMT+1]

[Ovu poruku je menjao blekmor dana 09.10.2013. u 19:47 GMT+1]
[ dusans @ 08.10.2013. 16:05 ] @
^ A šta je sa subtype polimorfizmom?
Ti ili nisi radio ništa ozbiljno putem OOP-a ili nas zezaš.

[Ovu poruku je menjao dusans dana 08.10.2013. u 17:27 GMT+1]
[ Rapaic Rajko @ 08.10.2013. 19:16 ] @
Uh, blekmor... nisi pazljivo citao gornju diskusiju :).

1) Java FORSIRA virtualne metode, u smislu da ne postoje non-virtual metode (sve metode su virtual). Standard kaze da treba da postoji mogucnost izbora - virtual ili non-virtual.
2) OOP bez virtualnih metoda bi bio k'o supa bez mesa ;). Polimorfizam je fantasticna tekovina objektnog programiranja, tu nema spora.

Pitanje teme je (ponavljam se): ZASTO java nema non-virtual metode?

Pozz
[ bantu @ 09.10.2013. 06:58 ] @
Zato što nema potrebe za time. :)
[ Rapaic Rajko @ 09.10.2013. 09:26 ] @
Eh, bas... ima neki jak razlog, ubedjen sam.

Tokom ucenja jave, prozvakao sam 3-4 tutorial-a i predavanja; svi se razlikuju po aktuelnoj verziji jave u momentu pisanja istih. Tako da se lepo moze videti kako su autori/planeri razvoja jave iz verzije u verziju ubacivali ponesto iz drugih jezika. (To je jos jedna moja zamerka javi: vrlo losa down kompatibilnost). Hocemo li docekati da se u nekoj buducoj verziji pojavi keyword 'nonvirtual' ;) ? Tesko, jer kad nije dosad... nece nikad :).

Pozz
[ Java Beograd @ 09.10.2013. 09:38 ] @
Kad kreneš da zarađuješ programirajući u Javi, sve ćeš to posmatrati drugačije. Onda teoretisanje tipa tiger animal mamal i ko šta kaže brzo padne u vodu.
[ zoranix @ 09.10.2013. 10:35 ] @
Teško da će ovo bilo kome zatrebati...
Programeri koji dolaze sa drugih jezika obično ne mogu da "žive" bez nekih stvari koje su recimo radile na C#, ili C++. S druge strane kada te zatrpa posao videćeš da moraš praktično da rešavaš probleme. Nakon dužeg vremena primetićemo da je naš kood zatrpan "glupostima" koje su posledica copy/paste sistema i da sva lepota umire s time. Na kraju kada Vaša aplikacija proradi kako valja i kada "vodenica promelje", nastaviće da melje kako je i započela, jer nas posao tera da gradimo druge "vodenice" i nemamo vremena (pa i pare su bitne!) da se vraćamo u stari kood i čisteći ga pokvarimo nešto.
Za ovih 30-tak godina sam se nagledao prljavština u mojim i tuđim softverima, da se ponekad pitam kako je to uopšte radilo do danas!
[ Rapaic Rajko @ 09.10.2013. 11:29 ] @
Citat:
Java Beograd:
Kad kreneš da zarađuješ programirajući u Javi, sve ćeš to posmatrati drugačije. Onda teoretisanje tipa tiger animal mamal i ko šta kaže brzo padne u vodu.


Paaa... vec zaradjujem :) . I priznajem da sam ocaran, java ima MOC koja se moze osetiti. A eclipse (na kojem sam ucio) i NetBeans (koji drljam na poslu) pruzaju izuzetan komfor pri radu; ne znam koji je bolji :). Poklopilo se da se (spomenuti) tutorijali bave pretezno konzolnim aplikacijama, koje su upravo tema rada ovde (i thread-ovi, mmm) i - eto me u elementu :).

A sto se tice teoretisanja, pa to je vazno: i sam OOP koncept je veoma apstraktna tvorevina, i takodje plod necijeg mudrovanja (teoretisanja) ;)

Hvala vam svima jos jednom na vrlo lepoj diskusiji!

Pozz

[ Shadowed @ 09.10.2013. 12:13 ] @
Da se moze samo sa virtuelnim funkcijama - moze se. Da me neko pita da li bih voleo da u programskom jeziku koji koristim postoje samo virtuelne ili da postoji mogucnost i non-virtual, pa, ipak bih odabrao postojanje i non-virtual. Ne moz' da skodi a moglo bi da koristi :)


Citat:
Rapaic Rajko: A eclipse (na kojem sam ucio) i NetBeans (koji drljam na poslu) pruzaju izuzetan komfor pri radu

Ovo za eclipse mi je tesko poverovati :) Eclipse i komfor su, sto se mene tice, dva nespojiva pojma...
[ Burgos @ 09.10.2013. 12:42 ] @
Citat:
Rapaic Rajko:
A eclipse (na kojem sam ucio) i NetBeans (koji drljam na poslu) pruzaju izuzetan komfor pri radu; ne znam koji je bolji :).



NetBeans.
[ blekmor @ 09.10.2013. 18:45 ] @
Izvinjavam se zbog kiksa u pisanju. Post koji sam ranije napisao ima jednu gresku - nisam pricao o virtualnim fukcijama, nego non-virtual.
Hvala sto ste me upozorili na ovakav kiks.
Non virtual fukcije nisu potrebne. Zeljeno ponasanje se jako jednostavno moze "simulirati" obicnom(virtualnim) fukcija tako sto reorganizujemo klase i interfejse.
Nadam se da je sada razumljivije ono sto sam napisao ranije , pozdrav.
[ srki @ 23.01.2014. 16:05 ] @
Citat:
Rapaic Rajko:
Ne znam kako vi, ali meni licno je ignorisanje "virtual-override" keywords veliki minus za javu. To cak narusava koncept OOP-a, rekao bih, a i opterecuje procesor (ili rasterecuje? to je ona prica sa VMT tabelama... hmmm). Programer mora imati mogucnost izbora virtual ili ne (moje misljenje, svakako).

Nepostojanje non-virtual metoda je veliki plus za javu! Virtuelne metode su srz polimofrizma. i to ne samo da ne narusava koncept OOP vec sprecava korisnika da narusi koncepte OOPa. Dacu primer na dnu posta.

Moje misljenje je da je veliki minus kod C++ i C# sto su metode non-virtual.

Citat:
Java Beograd:
Kad kreneš da zarađuješ programirajući u Javi, sve ćeš to posmatrati drugačije. Onda teoretisanje tipa tiger animal mamal i ko šta kaže brzo padne u vodu.

thumbs up!

Citat:
Shadowed:
Da se moze samo sa virtuelnim funkcijama - moze se. Da me neko pita da li bih voleo da u programskom jeziku koji koristim postoje samo virtuelne ili da postoji mogucnost i non-virtual, pa, ipak bih odabrao postojanje i non-virtual. Ne moz' da skodi a moglo bi da koristi :)

Moze da skodi jer iz koda neces znati da li je metoda vezana za klasu ili za instancu. Non-virtuelne metode su vezane za klasu a to iz koda neces znati. Zato je bolje napraviti static metodu koja ce da prima objekat te klase kao parametar.

Ako u javi imamo
Code:
public class ClassB extends ClassA {
    @Override 
    public void trci() {
    }
}
i objekat
Code:
ClassA obj=new ClassB();

Ako pozoves obj.trci() kako ces iz koda da znas da li ce to da postuje pravila polimorfizma ili ce da zove metodu koja je vezana za klasu ClassA? Non-virtuelne metode narusavaju principe OOP.
Sa druge strane znamo da su staticne metode vezane za klasu pa ako hoces da zoves metodu koja je vezana za klasu ClassA mozes da definises metod:
Code:
public static trci(ClassA obj)
i da je pozoves sa
Code:
ClassA.trci(obj);
Tako ces iz koda znati da li zoves metodu koja je polimorfna ili je vezana za klasu i za koju klasu.

Pozz.
[ Laki123 @ 07.04.2014. 20:09 ] @
Stari intervju sa Anders Hejlsbergom u vezi virtual funkcija u c#
Citat:
Summary
Anders Hejlsberg, the lead C# architect, talks with Bruce Eckel and Bill Venners about why C# instance methods are non-virtual by default and why programmers must explicitly indicate an override.

Versioning, Virtual, and Override
[ Rapaic Rajko @ 08.04.2014. 11:52 ] @
Pogledah bolje, to je cuveni Anders kojeg je M$ pokupio (sa jos nekolicinom njih) iz Borland-a, ponudom koja se ne odbija (po prici, blanko ugovori - sami da sebi upisu plate ).
E, to behu vremena...

Pozz

P.S. Lik je autor TurboPascal-a i Delphi-ja... ako ima Boga medj' programerima, on je.