[ Whitewater @ 27.11.2018. 18:31 ] @
da li bi ste preporucili javu ili c++ ili nesto trece mozda ?
[ Shadowed @ 27.11.2018. 19:49 ] @
Bih.
[ Whitewater @ 27.11.2018. 20:29 ] @
cemu bi dao prijoritet
[ Shadowed @ 27.11.2018. 23:08 ] @
To vec zavisi sta ti je cilj - sta hoces da radis ili postignes.
[ Whitewater @ 28.11.2018. 06:20 ] @
pa rekao sam cilj mi je da izvidim OO.

Da li je C++ logican nastavak C ?
[ jablan @ 28.11.2018. 09:46 ] @
Ako hoćeš samo da naučiš OO, najbolje Ruby ili Smalltalk.
[ djordjeno @ 28.11.2018. 11:22 ] @
Citat:
Whitewater: pa rekao sam cilj mi je da izvidim OO.


Sa akademskog pristupa ili zivotnog, primenljivog u praksi?
[ brux002 @ 28.11.2018. 15:31 ] @
Java, Ruby, Python ili C# ako zelis da naucis klasni OO, JavaScript ako zelis da naucis prototipni (besklasni) OO.

Svi su vrlo trazeni na trzistu rada (pogotovo Java i JS)
[ Whitewater @ 28.11.2018. 18:51 ] @
da budem iskren vise bih hteo nesto akademski. Npr tekst saga o oop mi se veoma svideo.

samo da kazem da mi je jedan prijatelj koji je profi kad sam se pre par godina interesovao prporucio knjige Bruce Eckel Thinking in Java i Thinking in C++ ali je na ovom nivou za mene to ipak visa matematika...
[ mjanjic @ 28.11.2018. 21:10 ] @
Imaš na sajtu ETF-a (druga sekcija) više kurseva na tu temu: https://rti.etf.bg.ac.rs/

Ako hoćeš da biraš jezik, imaš ovde predložene kurseve za različite jezike: http://www.java67.com/2018/02/...rogramming-online-courses.html
[ jablan @ 29.11.2018. 09:57 ] @
Citat:
Whitewater:
da budem iskren vise bih hteo nesto akademski.

Ruby je čist OO jezik i lak je za učenje. Java nije čist OO (multiparadigmatični je jezik) i može biti nešto teži za učenje, mada je sa stanovišta tržišta rada verovatno isplativiji. C++ zaobiđi dok dobro ne savladaš sve prethodno.
[ Zlatni_bg @ 29.11.2018. 10:43 ] @
Hm, po meni bi logicniji pristup bio ucenje odabranog jezika, pa prelazak na OOP u tom jeziku. Ne ucenje jezika striktno zbog OOP, pa posle bataljivanje istog (kao sto vidim da je ovde slucaj sa C, a pokretac teme svakih par dana menja interes).
[ jablan @ 29.11.2018. 15:14 ] @
Sve zavisi. Učenje bilo kog jezika nije bačeno vreme (npr. mogu svesrdno da preporučim knjigu "seven languages in seven weeks" kojoj je poenta upravo to, upoznavanje sa različitim programskim paradigmama kroz učenje više jezika), a i Ruby uopšte nije beskoristan jezik, i dalje je vrlo upotrebljiv (doduše prevashodno samo za web). Sa druge strane, učenje OO koncepata kroz jezike kojima je OO samo jedna "štikla" u tabelama poređenja sa ostalim jezicima (što bi se na engleskom reklo "afterthought") potencijalno vodi ka nerazumevanju ili delimičnom razumevanju materije.
[ Ivan Dimkovic @ 29.11.2018. 15:21 ] @
Citat:
jablan:
Citat:
Whitewater:
da budem iskren vise bih hteo nesto akademski.

Ruby je čist OO jezik i lak je za učenje. Java nije čist OO (multiparadigmatični je jezik) i može biti nešto teži za učenje, mada je sa stanovišta tržišta rada verovatno isplativiji. C++ zaobiđi dok dobro ne savladaš sve prethodno.


+1, ako ti je akademsko ucenje prioritet pocni od ovoga sto Jablan savetuje (Ruby ili Smalltalk)

A to je dobro bez obzira na "akademiju" ili ne ako si pocetnik.

Posle vec vidi sta se trazi na trzistu. C++ kao jezik za OO ucenje zaobidji zato sto vrlo lako moze da te "navuce" da pises los kod ako nisi senior pa na kraju neces nauciti dobro OOP a verovatno ces i pisati nesiguran kod koji je potencijalno minsko polje.
[ Whitewater @ 29.11.2018. 19:40 ] @
Citat:
Zlatni_bg:
Hm, po meni bi logicniji pristup bio ucenje odabranog jezika, pa prelazak na OOP u tom jeziku. Ne ucenje jezika striktno zbog OOP, pa posle bataljivanje istog (kao sto vidim da je ovde slucaj sa C, a pokretac teme svakih par dana menja interes).


nista ja nisam batalio ! Poceo sam sa PHP, pa shvatio da mi treba HTML. Tu sam naravno naleteo na JS. I onda sam shvatio da je najbolje da ipak naucim prvo neki klasican jezik, a to je C.

vec 3 nedelje sam sa C procitao sam celu knjigu od Prata i proradio neke primere koristeci code:blocks, radio na Windows i linux-u.

Ne kazem da sam postao ekspert i zasto bih batalio C ako hocu da se upoznam sa OO ?

PHP i web drustvo su sada na stand-by.

Moj cilj je da udarim temelje za bavljenje programiranjem...

Sad citam na safarionline The Object Oriented Thought Process od Weisberga...

[ Whitewater @ 29.11.2018. 19:47 ] @
Citat:
jablan:
Sve zavisi. Učenje bilo kog jezika nije bačeno vreme (npr. mogu svesrdno da preporučim knjigu "seven languages in seven weeks" kojoj je poenta upravo to, upoznavanje sa različitim programskim paradigmama kroz učenje više jezika), a i Ruby uopšte nije beskoristan jezik, i dalje je vrlo upotrebljiv (doduše prevashodno samo za web). Sa druge strane, učenje OO koncepata kroz jezike kojima je OO samo jedna "štikla" u tabelama poređenja sa ostalim jezicima (što bi se na engleskom reklo "afterthought") potencijalno vodi ka nerazumevanju ili delimičnom razumevanju materije.


hvala ti na preporuci ali jos pre nego sto si spomenuo Ruby krenuo sam da citam Weisberga (vidi gore). Knjiga je pitka, lepo vozim... Ubacuje java kod ali na razumljiv nacin i cin i koristi UML dijagrame.

E to stvarno nisam cuo moram priznati. UML ? To je pozeljno ?
[ Whitewater @ 29.11.2018. 20:14 ] @
Citat:
Ivan Dimkovic:
Citat:
jablan:
Citat:
Whitewater:
da budem iskren vise bih hteo nesto akademski.

Ruby je čist OO jezik i lak je za učenje. Java nije čist OO (multiparadigmatični je jezik) i može biti nešto teži za učenje, mada je sa stanovišta tržišta rada verovatno isplativiji. C++ zaobiđi dok dobro ne savladaš sve prethodno.


+1, ako ti je akademsko ucenje prioritet pocni od ovoga sto Jablan savetuje (Ruby ili Smalltalk)

A to je dobro bez obzira na "akademiju" ili ne ako si pocetnik.

Posle vec vidi sta se trazi na trzistu. C++ kao jezik za OO ucenje zaobidji zato sto vrlo lako moze da te "navuce" da pises los kod ako nisi senior pa na kraju neces nauciti dobro OOP a verovatno ces i pisati nesiguran kod koji je potencijalno minsko polje.


imacu u vidu mnoga upozorenja oko C++ mada me Prata knjiga neodoljivo privlaci...
[ jablan @ 29.11.2018. 21:45 ] @
Citat:
online The Object Oriented Thought Process od Weisberga...


https://www.goodreads.com/book...bject-oriented-thought-process

Citat:

I was not a fan at all of this book. It's like one of the object-oriented programming books of the 1990s, telling you all about how great objects are then showing Java code riddled with statics and public mutator methods.

All the hallmarks are there: the implementation-derived interfaces, pointless hierarchies where we learn that Dogs are Canines are Mammals and that Squares are Rectangles are Shapes, and more.

The book has very little on what I would consider object-oriented thought. There is a superficial chapter on design patterns. Nothing useful on domain modeling. Nothing on the kinds of principles that were already evinced in Bertrand Meyer's writing. Nothing on message-passing, prototypical inheritance, design by contract or anything that doesn't conform to a Java 1.3 view of OOP. Nothing on capturing intent in designing objects.

It appears as if the author's perspective on OOP is that it's a useful way to wrap procedural code for use in modern systems, rather than being a system design process in its own right that happens to sometimes incorporate procedural code.

I would not recommend this as an introduction to modern Object-Oriented techniques: unfortunately I can't think of anything that does fill that gap.


Dobar indikator da je knjiga (tutorijal, kurs...) o OOP loša, je kad krenu da pričaju o klasama na primeru Pas -> Životinja ili Trougao -> GeometrijskaFigura. Nije mi jasno zašto ne uzmu bilo koji primer iz bilo koje standardne OOP biblioteke (Rational -> Numeric, File -> IO itd)
[ mjanjic @ 29.11.2018. 21:51 ] @
Ma uzmeš lepo jedan primer troslojne aplikacije (obične, ne MVC i sl., nego se pratično naprave 3 klase koje rade 3 različite stvari, ono jedna pristupa bazi, druga obrađuje podatke, a treća prikazuje te podatke i prima zahteve od korisnika), i tu se lepo vidi čemu objekti, nasleđivanje, posebno koja klasa je član koje druge klase, kako se instancira i čemu sve to.

Na teorijskim primerima datim u knjigama često izgubi ta suština, jer se ili prikazuje samo mehanizam zavisnosti između klasa, nasleđivanje i druge osobine OOP, ili se ti primeri zakomplikuju stvarima koje nemaju mnogo veze sa suštinom primera kojim se ilustruje jedna od mnogih mogućnosti OOP.



A za funkcionalno programiranje...
Videh da na nekom univerzitetu u okviru nekog kursa rade Pyret, valjda će mu u daljem razvoju negde ubaciti OOP.


[Ovu poruku je menjao mjanjic dana 29.11.2018. u 23:05 GMT+1]
[ Zlatni_bg @ 30.11.2018. 02:56 ] @
Citat:
Whitewater:
Citat:
Zlatni_bg:
Hm, po meni bi logicniji pristup bio ucenje odabranog jezika, pa prelazak na OOP u tom jeziku. Ne ucenje jezika striktno zbog OOP, pa posle bataljivanje istog (kao sto vidim da je ovde slucaj sa C, a pokretac teme svakih par dana menja interes).


nista ja nisam batalio ! Poceo sam sa PHP, pa shvatio da mi treba HTML. Tu sam naravno naleteo na JS. I onda sam shvatio da je najbolje da ipak naucim prvo neki klasican jezik, a to je C.

vec 3 nedelje sam sa C procitao sam celu knjigu od Prata i proradio neke primere koristeci code:blocks, radio na Windows i linux-u.

Ne kazem da sam postao ekspert i zasto bih batalio C ako hocu da se upoznam sa OO ?

PHP i web drustvo su sada na stand-by.

Moj cilj je da udarim temelje za bavljenje programiranjem...

Sad citam na safarionline The Object Oriented Thought Process od Weisberga...



Nemoj se ljutiti, nisam hteo da te uvredim :) Poenta je da svakom jeziku moras da posvetis neko vreme, a C uopste nije los jezik za pocetak ako zelis da razumes racunare i neki sub-low-level programming. Iz teme u kojoj si pisao da ti pointeri nisu jasni sam zakljucio da nisi zeleo da se zadrzavas na njemu vec odmah da skocis na OOP. Imamo Baneta, on je verovatno najbolji C programer na forumu, koji ce ti reci da za 3 nedelje sigurno neces moci da pokacis ni osnove ako si tek poceo sa programiranjem generalno, i dobro slusaj njegove savete.

PHP & web ne treba da ti bude na stand by. Obrazlozicu zasto.

Pazi, proceduralno programiranje je meni dugi niz godina zavrsavalo posao. Mozes sve dan danas da napises i tako. Tek kada osetis potrebu za prelaz, ja mislim da treba da predjes na OOP u nekom jeziku. A za pocetak je neophodno da u tom jeziku dobro naucis sintaksu i dosta primera, kao i da izradis par aplikacija. Najlaksi primer kako da sve to preskocis je na primer, Delphi. Tu ces imati rapid-app-development gde ces uglavnom koristiti njegove klase i pisati OOP. To je ono sto niko nije spomenuo ovde. Osnove paskala ces vrlo lako nauciti ako si radio C. Verovatno Delphi niko nije spomenuo danas jer su ga pojeli mnogi drugi jezici, ali za lonewolf programiranje je i dalje dobra stvar. Vrlo brzo dobijes potpunu aplikaciju sa GUI-jem, bilo za linux, bilo za android, bilo za windows, HTML5, sta vec sve moze da kompajlira/wrappuje - ne znam dokle se stiglo s tim danas.

Dalja prica i obrazlozenje zasto da ne batalis i ne stavljas PHP na standby.

Mali je broj (pogotovu u Srbiji) dobrih PHP programera. 90% njih je dalo sebi tu titulu jer rade WordPress sajtove koje eventualno ili uopste ne modifikuju, neki prave neke one-page aplikacije od 100 linija koda, a 10% ljudi radi pravu stvar sa PHP-om. PHP takodje ima VRHUNSKI odradjen OOP ako pratis best-practices, pogotovu sa PHP7. Eksremno je lak, a ako pravis neki API, ne treba ti ni HTML niti bilo sta drugo sem PHP-a. Takodje u potpunosti mozes da koristis MVC, a kad budes u mogucnosti mozes da predjes i na FW koji koristi taj princip, recimo Laravel.

Kontrirajuci svime sto su ti predlozili ovde, Javu itd, predlazem ti da skines Delphi koji ima besplatnu verziju sada, i da nastavis svoj rad u PHP-u u kom ces praviti OOP aplikacije. Delphi ti verovatno nece zaraditi novac ukoliko sam ne guras svoju aplikaciju na trziste, ali dobri PHP programeri se ubijaju od posla i para. A ako bas tezis ka OOP i radio si C (i zalio se na tipove) imas ogroman potencijal da budes dobar PHP programer jer gomila ljudi u PHP ni ne koristi tipove i definisanje tipa promenljive.

Zelim ti uspeh u daljem ucenju i zaista se nadam da me nisi pogresno shvatio, tu sam za dalje savetovanje.
[ Whitewater @ 30.11.2018. 04:56 ] @
zlatni:

pa istina je da sam vas tamo 6 strana pitao kako da postavim IDE za PHP sa debugger i onda sam kao to batalio.

Privremeno. Privremeno. Nebojse ja cu opet doci da vas nerviram )))

Sto se tice C, pristup Prate i vecine knjiga nije dobar jer objasnjavaju pointerv preko array. Tu se ne vidi prava prednost pointera. Ali posle sam pitao i onda sam nasao strukturu podataka LIST i konkretno implementiju preko pointera. E tako moze da se razume zasto koristimo pointere, recimo kod polinoma koji nemaju sve stepene monoma itd... dinamicka vs staticka alokacija memorije...

Tu sam jedno 10tak dana potrosio, cak sam sisao i do nekih stvari u Assembleru, nacinu alokacije memorije i da sad ne davim dalje... citao developer manual sa AMD web site jer imama AMD E1 processor.

Mislim da se vracam PHP za nekih 7 dana, a onda cu malo cackati i taj DELPHI.



[ Zlatni_bg @ 30.11.2018. 05:09 ] @
Mozda sam zaboravio za debagera za PHP. Ono sto bih savetovao pocetnicima je samo paljenje error reportinga, bice sasvim dovoljno za pocetak.
[ Whitewater @ 30.11.2018. 05:12 ] @
Citat:
Zlatni_bg: Mozda sam zaboravio za debagera za PHP. Ono sto bih savetovao pocetnicima je samo paljenje error reportinga, bice sasvim dovoljno za pocetak.


okay imacu to u vidu. poslao sam ti sliku dokaz da sam pribavio tesku artiljeriju jer sam stekao utisak da mislis da te foliram.
[ Nedeljko @ 30.11.2018. 18:21 ] @
Citat:
jablan: Dobar indikator da je knjiga (tutorijal, kurs...) o OOP loša, je kad krenu da pričaju o klasama na primeru Pas -> Životinja ili Trougao -> GeometrijskaFigura. Nije mi jasno zašto ne uzmu bilo koji primer iz bilo koje standardne OOP biblioteke (Rational -> Numeric, File -> IO itd)

Da mi je znati šta je loše u uzimanju opšte poznatih primera.
[ Whitewater @ 30.11.2018. 18:28 ] @
u redu ubedili ste me vracam se PHP odmah.
[ mjanjic @ 01.12.2018. 00:04 ] @
Citat:
Nedeljko:
Citat:
jablan: Dobar indikator da je knjiga (tutorijal, kurs...) o OOP loša, je kad krenu da pričaju o klasama na primeru Pas -> Životinja ili Trougao -> GeometrijskaFigura. Nije mi jasno zašto ne uzmu bilo koji primer iz bilo koje standardne OOP biblioteke (Rational -> Numeric, File -> IO itd)

Da mi je znati šta je loše u uzimanju opšte poznatih primera.


Veoma retko se koriste u praksi, tako da početnici nauče to kao pesmicu, a nemaju pojma gde se u praksi koristi nasleđivanje niti šta je svrha.

Problem je što je proces u praksi obrnut - prvo se u projektovanju pojave pojedinačne klase, pa kad se utvrdi da neke od njih imaju značajan broj istih atributa (i eventualno metoda), onda se vrši generalizacija - kreira se apstraktna klasa iz koje se izvode odgovarajuće klase.

Zašto, šta je problem imati sve to bez nasleđivanja?
Pa, šta ako rešite da neki od atributa umesto tipa Float budu Double, ili umesto Int budu String (tokom refactoring procesa ili iz nekog drugog razloga)? Ako je jedan od tih atributa deklarisan u svakoj klasi nezavisno, ko će da juri gde se on sve nalazi kako bi promenio deklaraciju? Lakše je ako je deklarisan u apstraktnoj klasi (ne mora da bude apstraktna u smislu kao kod Jave).


Ali, opet ni to nije očigledno kod jednostavnih klasa.
Dovoljno je pogledati GUI aplikacije, svaki dijalog ima isti oblik (pravougaonik), okvir, moguće kontrolne elemente... lakše je napraviti jednu klasu pa izvođenjem kreirati različite vrste dijaloga, nego raditi sa 100 različitih klasa koje se razlikuju za po jedan atribut, jer u slučaju da treba nešto izmeniti kod svih 100 vrsta dijaloga, samo se izmeni u apstraktnoj klasi.


Zato se početnicima zada problem sa 30 različitih tipova knjiga (koje imaju deo istih atributa i metoda, čak metode mogu biti i sve iste), pa videti da li će kreirati 30 različitih klasa ili koristiti nasleđivanje.
Onima koji naprave 30 različitih klasa reći da sve knjige imaju još 10 novih atributa, a kad i to odrade, kažete im da se zahteva još 50 novih vrsta knjiga.

Ako sve to i urade, onda im pokažete primer sa nasleđivanjem i pitate ih koji bi kod radije održavali i unapređivali.
[ Branimir Maksimovic @ 01.12.2018. 06:38 ] @
https://codeburst.io/inheritan...vil-stop-using-it-6c4f1caf5117

edit Apropo ovoga Go i Rust su potpuno izbacili nasledjivanje kao koncept a sa tim i klase, ono sto samtraju ispravnom praksom a to su interfejsi
to su ostavili.
[ Nedeljko @ 01.12.2018. 07:40 ] @
@mjanjic

Pa, valjda treba da razumeju koncepte, a ne da nabubaju napamet veze između bibliotečkih klasa.

Dao si primer sa vrstama knjiga, koji je sličan primeru sa životinjama po tome što je zasnovan na nečemu opšte poznatom iz stvarnog sveta.
[ Nedeljko @ 01.12.2018. 08:01 ] @
@Branimir Maksimovic

Meni se gade ti fašistički jezici, koji me prave budalom i uče me šta i kako treba da radim. Zato nikada nisam mogao da se prebacim sa C/C++ na nešto drugo, sem Python-a za sitno. Dobro, imam i neke bash skripte. Takođe, radio sam u drugim jezicima (npr. Java) za posao, koristio JS za frontend. Međutim, za OOP, samo C++. Pruža mi svakakve mogućnosti, tako da mogu da biram šta ću da koristim. Kada jednom navikneš na slobodu, posle ne možeš u konc-logor.
[ Branimir Maksimovic @ 01.12.2018. 08:23 ] @
Ne kapiram, kakvi su to fasisticki jezici? Jezici koji nemaju klase i nasledjivanje su fasisticki ili je to neka druga paradigma?
Go i Rust autori su videli kako funkcionalni jezici lepo zive bez toga, pa su i oni krenuli tim putem... jos pre 10 godina su ljudi uvideli
da je duboka hijerarhija klasa anti-patern i da nasledjivanje ne treba da ide vise od jednog nivoa u dubinu. Logican zakljucak
je da onda ne treba nikakve podatke stavljati u baznu klasu, pa iz toga sledi da su interfejsi jedina logicna implementacija
nasledjivanja u modernom OOP-u. Iz toga sledi da je nasledjivanje potpuno nepotrebno, i et orezultata ;p
Procitaj onaj tekst koji sam linkovao ;p
[ Shadowed @ 01.12.2018. 08:51 ] @
Citat:
Whitewater:
u redu ubedili ste me vracam se PHP odmah.

Upropastiste coveka
[ Branimir Maksimovic @ 01.12.2018. 08:53 ] @
To ti je ono put oko sveta programskih jezika za 10 dana ;)
[ negyxo @ 01.12.2018. 09:06 ] @
Citat:
Branimir Maksimovichttps://codeburst.io/inheritan...vil-stop-using-it-6c4f1caf5117

edit Apropo ovoga Go i Rust su potpuno izbacili nasledjivanje kao koncept a sa tim i klase, ono sto samtraju ispravnom praksom a to su interfejsi
to su ostavili.


Skoro pa prvi komentar :D

Citat:

Inheritance is fundamental base of OOP, what you try to say is stop using OOP but in fact you demonstrate „I don’t know how to use it properly“.



Od kada je pocela ova trka oko funkcionalnih konstrukta (u svim jezicima), odjednom OOP postaje losa opcija.

Sto se tice interface-a, sve zavisi za sta, kako i gde ih koristis (recimo u nominalnom type sistemu, interfejsi su vise zlo nego korist, opet ne zbog samih interfejsa nego zbog zloupotrebe, dok u strukturalnom type sistemu, interfejsi imaju mnogo vise smisla zbog fleksibilnosti).
[ Branimir Maksimovic @ 01.12.2018. 09:21 ] @
Najveci razlog zbog koga se prelazi na funkcionalnu paradigmu je multi threading. OOP podrazumeva mutable shared state sto se smatra za zlo kada se threadovi ukljuce u igru.
Sto se tice interface-a ne vidim kakve veze to ima sa type sistemom. Haskell i Rust imaju nominalni type sistem a interfejsi se tu odlicno uklapaju u genericko programiranje,
zato sto su u ovom slucaju genericki parametri ograniceni interfejsima koje implementiraju. Moguce je naravno i upotrebiti ih u dinamickom bajndovanju i ne vidim nista
sto tu smeta i kako bi se moglo zloupotrebiti vise nego inheritance.
Da ne bi sad pricali sta bi bilo kad bi bilo, da li mozes da navedes primer zloupotrebe interfejsa u jeziku sa nominalnim type sistermom, pa da znamo o cemu pricas ;p?
[ Whitewater @ 01.12.2018. 09:46 ] @
hvala vam na brojnim savetima malo sam pogledao predloge: Ruby, Smalltalk sisao i do Simule stare dobre, razmisljao o Object C i Swift... Jednom se mora preseci, a ja sam presekao:

idem na C++ !

glavin razlog je sto je Prata napisao C i C++ knjigu, a svidja mi se kako je uradio C mada me smorio sa pointerima. Stekao sam poverenje u njega jer detaljno objasnjava...

pozdrav veterani.

odlazim u noc u mecavu, pokusacu da se probijem. Ako zaginem niko me se nece secati, a ako prezivim uci cu u legendu.

ja sam ovaj na lokomotivi 2:20



[ Branimir Maksimovic @ 01.12.2018. 09:47 ] @
Slobodno postavljaj pitanja o C++-u na forumu ;)
[ negyxo @ 01.12.2018. 10:51 ] @
Citat:
Branimir Maksimovic:
Najveci razlog zbog koga se prelazi na funkcionalnu paradigmu je multi threading. OOP podrazumeva mutable shared state sto se smatra za zlo kada se threadovi ukljuce u igru.
Sto se tice interface-a ne vidim kakve veze to ima sa type sistemom. Haskell i Rust imaju nominalni type sistem a interfejsi se tu odlicno uklapaju u genericko programiranje,
zato sto su u ovom slucaju genericki parametri ograniceni interfejsima koje implementiraju. Moguce je naravno i upotrebiti ih u dinamickom bajndovanju i ne vidim nista
sto tu smeta i kako bi se moglo zloupotrebiti vise nego inheritance.
Da ne bi sad pricali sta bi bilo kad bi bilo, da li mozes da navedes primer zloupotrebe interfejsa u jeziku sa nominalnim type sistermom, pa da znamo o cemu pricas ;p?


Hm, mutability ne bi trebalo da ima veze sa paradigmom, tj. i nema. Immutable tipove podataka mozes da imas u kom god hoces jeziku, i cak sta vise, imas dosta dobrih implementacija u OOP (recimo, u C#, Roslyn ima jako lep immutable API, dok recimo neki od js librarary imaju toliko los API da ti se "zgadi" immutable pristup, iako to nema veze sa patternom, nego sa losom imeplementacijom).

Sto se tice interfejsa, u nominalnom type sistemu, problem je kada definises da ocekujes odredjeni interface (contract) on mora biti tog tipa i samim tim imas manje fleksibilnosti po pitanju prosledjivanja vrednosti, dok u strukturalnom nemas ovo ogranicenje, jer ti nije bitno kako se zove interfejs, nego njegov oblik. E sad, naravno, to sto definises u nominalnom type sistem koji interfejs ocekujes i nije toliki problem (u smislu da mora biti bas taj), nego je problem, kada neko uzme i pocne da koristi "design patterne" i "best practices", tako sto za svaku, skoro svaku, stvar uzme i definise interfejs. To je silovanje type sistema. To u prevodu znaci, da ti imas bukvlano interface pa implementaciju, ne postoji na primer klasa koja nema bazni interfejs. Sve to ludilo dolazi od dependency injection patterna (i containera), ljudi su skontali da je savim cool da mozes da injectujes po potrebli sta ti treba, sto naravno nije lose, ali je lose da radis sa svim stvarima to (od recimo 100 klasa, ti recimo imas potrebu mozda za 5 klasa da budu injectovane, ali zasto da bude prosto kada moze da bude komplikovano, pa onda zarad onih 5% predizajniras celu aplikaciju i svuda gurnes interfejs). No da budem iskren, ovo ludlilo najvise sam vidjao u "enterprise" aplikacijima i firmama koje se oslanjaju na .NET I Java (nije ni cudo sto posle ljudi imaju averziju prema ovim tehnologijama kada od proste stvari namestis azdaju kojoj ne znas ni gde joj je pocetak ni kraj).
[ Branimir Maksimovic @ 01.12.2018. 11:10 ] @
"Sto se tice interfejsa, u nominalnom type sistemu, problem je kada definises da ocekujes odredjeni interface (contract) on mora biti tog tipa i samim tim imas manje fleksibilnosti po pitanju prosledjivanja vrednosti, dok u strukturalnom nemas ovo ogranicenje, jer ti nije bitno kako se zove interfejs, nego njegov oblik"

Nije mi jasno o cemu pricas. Moze neki primer?
[ Nedeljko @ 01.12.2018. 12:02 ] @
@Branimir Maksimović


Pročitaj naslov teme. Kakvi crni funkcionalni jezici! Nemam ja ništa protiv njih, ali tema je OOP, a funkcionalna paradigma je off topic.

C# je fašistički jezik jer zabranjuje višestruko nasleđivanje klasa, već samo interfejsa. Isto važi za sve jezike koji uvode pojam interfejsa, koji je potpuno suvišan kada imaš višestruko nasleđivanje klasa.

Java je fašistički jezik uz dodatan razlog što nema prenošenje prostih tipova po referenci, a složenih po vrednosti i nema složene vrednosne tipove.

Python je fašistički jezik iz sličnog razloga. Ne da mi da biram šta de po vrednosti, a šta po referenci, nego moram da doproramiram kopiranje.

D je fašistički jezik jer su mu stringovi immutable i nema druge stringove koji bi bili mutable.


Kada jednom navikneš na C/C++ slobodu, ne želiš više nikada u konc-logor.
[ negyxo @ 01.12.2018. 12:29 ] @
Citat:
Branimir Maksimovic:
"Sto se tice interfejsa, u nominalnom type sistemu, problem je kada definises da ocekujes odredjeni interface (contract) on mora biti tog tipa i samim tim imas manje fleksibilnosti po pitanju prosledjivanja vrednosti, dok u strukturalnom nemas ovo ogranicenje, jer ti nije bitno kako se zove interfejs, nego njegov oblik"

Nije mi jasno o cemu pricas. Moze neki primer?


Moze, naravno, lakse je kroz primere.

Elem, recimo da imas neku funkciju koja prima interfejs, recimo ovako:

Code:

interface ISize 
{
   int x;
   int y;
   int width;
   int height;
}
void DrawRectangle(ISize size) { .. }


Da pozoves ovu f-ju iz nominalnog type sistema, imas dve opcije:

- da pronadjes ko implementira ovaj interface
- da sam implementiras interface

Kako god okrenes, neko mora da implementira interfejs jer tako je definisano kroz type sistem.

Ako pogledas strukturalni type sistem, onda nemas ovo ogranicenje, posto te ne zanima tacno da ispunis contract po imenu i obliku, nego samo po obliku. Drugim recima, mozes da konstruises "on the fly" interface i prolsedis, recimo:

Code:

DrawRectangle({
    x: 10,
    y: 10,
    width: 100,
    height: 50
})


Ovde u sustini koristis anoniman tip, ali to nije core feature, posto anonimne tipove imas i u nominalnim type sistemima, ali posto je tamo striktnije, ovo nece proci.

[ negyxo @ 01.12.2018. 12:39 ] @
Citat:
Nedeljko:
C# je fašistički jezik jer zabranjuje višestruko nasleđivanje klasa, već samo interfejsa. Isto važi za sve jezike koji uvode pojam interfejsa, koji je potpuno suvišan kada imaš višestruko nasleđivanje klasa.


Recimo, ja sam se bas zalio ovde pre nekoliko godina na ovo za C#, i moram priznati uzasno me je nerviralo, jer mi je neko nametnuo ogranicenje vestacki zarad mene samog, da ne bi kojim slucajem sam sebe minirao. Elem, posle par godina, shvatiio sam jednu stvar, ne, nije mi toliko kriticno da imam visestruko nasledjivanje (ali bih voleo da imam, i kada ima smisla da mogu da ga koristim), jer za vecinu stvari koje sam zeleo da uradim sa visestrukim nasledjivanjem u stvari pravi odgovor su bili mixini (kojih na zalost nema u C#). No, najveca mana C# nije visestruko nasledjivanje, nego nepostojanje non-null referentnih tipova (koje ce uskoro da bude podrzano).
[ Branimir Maksimovic @ 01.12.2018. 13:41 ] @
Citat:
Elem, recimo da imas neku funkciju koja prima interfejs, recimo ovako:

Code:
Code:

interface ISize 
{
   int x;
   int y;
   int width;
   int height;
}
void DrawRectangle(ISize size) { .. }



Da pozoves ovu f-ju iz nominalnog type sistema, imas dve opcije:

- da pronadjes ko implementira ovaj interface
- da sam implementiras interface


Nije to interfejs nego struktura. Interfejs nije struktura nego protokol.
Znaci ako uzimas kao parametar interfejs, koristis protokol da komuniciras sa objektom, pri tom je totalno nebitno
koja je struktura sam objekt.

Recimo:

Code:

pub trait Op{
    fn init()-> Self;
    fn mul(&self,rhs:&Self)->Self;
    fn add_assign(&mut self,rhs:&Self);
}

pub fn Mul<T:Op>(t:&mut [[T;4];4], a:&[[T;4];4], b:&[[T;4];4] ) {
  for i in 0..4 {
    for j in 0..4 {
      let mut sum:T = Op::init();
      for k in 0..4 {
        let c = a[i][k].mul(&b[k][j]);
        sum.add_assign(&c);
      }
      t[i][j]=sum;
    }
  }
}


Znaci uopste ne zalazis u to ko implementira interface samo si definisao protokol i to je to.


[ Nedeljko @ 01.12.2018. 14:14 ] @
Definišeš API. To naravno možeš i definisanjem klase bez atributa i implementacija metoda, pri čemu su sve metode virtuelne.
[ negyxo @ 01.12.2018. 14:46 ] @
Citat:
Branimir Maksimovic:
Nije to interfejs nego struktura. Interfejs nije struktura nego protokol.


Ajde da sada ne cepidlacimo, primer je maksimalno prost, nema potreba da sada definisemo sta je struktura sta je interface. U vecini jezika interface-i su prilicno "slobodni" pa tako mozes sve da definises, i property-e, fieldove (kako koji jezik sta vec zove) i funkcije. Znaci, to ne menja poentu onoga sto sam pisao, ti si dao komplikovaniji primer, samo ces teze opisati poentu. I da, poenta nije u tome kako da upotrebis interface kod sebe u implementaciji, nego kako ce onaj koji poziva tvoj code da prosledi tebi implementaciju tog interfejsa kojeg ocekujes. Kao sto vidimo, iz strukturalnog type sistema, ovo se definise on-the-fly, dok kod nominalnog nije moguce.

Samo da dopunim sebe, posto sam mozda bio nejsan. Kako bi ti u svom primeru pozvao funkciju Mul?


[Ovu poruku je menjao negyxo dana 01.12.2018. u 16:10 GMT+1]
[ Branimir Maksimovic @ 01.12.2018. 16:52 ] @
Mul pozivas za bilo koji tip koji implementira interfejs Op, u konkretnom primeru. Razlika izmedju interfejsa i klase/strukture je u tome sto interfejs nema podataka.
[ Branimir Maksimovic @ 01.12.2018. 16:53 ] @
Citat:
Nedeljko:
Definišeš API. To naravno možeš i definisanjem klase bez atributa i implementacija metoda, pri čemu su sve metode virtuelne.


Upravo tako. To je interfejs.
[ negyxo @ 01.12.2018. 17:17 ] @
Citat:
Branimir Maksimovic: Mul pozivas za bilo koji tip koji implementira interfejs Op, u konkretnom primeru. Razlika izmedju interfejsa i klase/strukture je u tome sto interfejs nema podataka.


Opet, ja zaista ne znam da li postoji univerzalna definicija interfejsa (sto je u ostalom i nebitno) ali znam bar dva jezika u kojima je moguce imati "naked" vrednosti, a da se ne vracaju iz funkcija. No, to nije poenta, poenta je da tvoja mul funkcija zahteva implementaciju interfejsa koji ne moze da se prosledi on-the-fly.
[ Branimir Maksimovic @ 01.12.2018. 20:34 ] @
Pa naravno da neki tip mora implementirati interfejs, ne kapiram sta ti to znaci on the fly. Mislis nesto kao lokalna klasa koja implementira interfejs?
Postoji i mogucnost default implementacije interfejsa, nemoj da se sekiras.
[ negyxo @ 01.12.2018. 21:06 ] @
Najbolje da pogledas kako radi recimo TypeScript, ili neki slican strukturalni type sistem.

Evo primer, uzecu interfejs koji samo ima metode, da ne bi isli sa kursa :)

Code:

interface IMessageConverter<TIn, TOut> {
        convertToJson: (object: TIn) => string;
        conertToObject: (json: string) => TOut;
}

function send<TIn, TOut>(converter: IMessageConverter<TIn, TOut>, object: TIn)  {
       const payload = converter.ConvertToJson(object);

       // ovo je pseudo code, posto fetch asinhrono radi i mora na Promise
       const response =  fetch(payload, ...);

       // vraca TOut
       return converter.convertToObject(response);
}


const myObject : Whatever = ....;

send(
    { 
        convertToJson: o => JSON.stringify(o),
        convertToObject: s => JSON.parse(s)
    }, 
    myObject);




Ako pogledas metodu send, ona prima interfejs, ali taj interfejs moze da se kreira on-the-fly, bas kao sto imas opciju u nominalnom type sistemu kada se ocekuje funkcija da prosledis lambdu umesto da pises negde implementaciju. Naravno, sve ovo mozes i ne moras da korists, za sve treba doza racionalnosti, sa ovim ako se pretera onda dobijes brdo code-a koji se ponavlja, a opet ako nemas ovu opciju onda dodjes u situaciju da nekad pises implementacije interfejsa za jako trivijalne stvari i to samo na jednom mestu, sto je prilicno smarajuce.

[ mjanjic @ 01.12.2018. 21:27 ] @


[Ovu poruku je menjao mjanjic dana 01.12.2018. u 22:37 GMT+1]
[ Branimir Maksimovic @ 01.12.2018. 22:12 ] @
Citat:
negyxo:
Najbolje da pogledas kako radi recimo TypeScript, ili neki slican strukturalni type sistem.

Evo primer, uzecu interfejs koji samo ima metode, da ne bi isli sa kursa :)

Code:

interface IMessageConverter<TIn, TOut> {
        convertToJson: (object: TIn) => string;
        conertToObject: (json: string) => TOut;
}

function send<TIn, TOut>(converter: IMessageConverter<TIn, TOut>, object: TIn)  {
       const payload = converter.ConvertToJson(object);

       // ovo je pseudo code, posto fetch asinhrono radi i mora na Promise
       const response =  fetch(payload, ...);

       // vraca TOut
       return converter.convertToObject(response);
}


const myObject : Whatever = ....;

send(
    { 
        convertToJson: o => JSON.stringify(o),
        convertToObject: s => JSON.parse(s)
    }, 
    myObject);




Ako pogledas metodu send, ona prima interfejs, ali taj interfejs moze da se kreira on-the-fly, bas kao sto imas opciju u nominalnom type sistemu kada se ocekuje funkcija da prosledis lambdu umesto da pises negde implementaciju. Naravno, sve ovo mozes i ne moras da korists, za sve treba doza racionalnosti, sa ovim ako se pretera onda dobijes brdo code-a koji se ponavlja, a opet ako nemas ovu opciju onda dodjes u situaciju da nekad pises implementacije interfejsa za jako trivijalne stvari i to samo na jednom mestu, sto je prilicno smarajuce.


Ok, ali gde ti tu vidis abuse? Ako jezik dozvoljava anonimnu implementaciju interfejsa, ne moras a mozes da je koristis. Tu dolazimo zapravo do sustine a to je pitanje lambda funkcija koje nisu OOP ;p
Funkcionalna paradigma je svuda zavladala i skoro pa zamenila OOP kompletno.

[ negyxo @ 01.12.2018. 22:44 ] @
Branimire, nisi pratio fabulu :D

Ne, zadnjih par komentara se odnosi na to kako strukturalni type sistem ti omogucuje da implementiras interface on-the-fly. Zloupotreba se odnosi na onaj deo koji sam opisao u drugom postu, kada uzmes i za svaku klasu namestis interface. To znaci, ako planiras da tvoj code koristis samo interno, i nema neki public deo, i nemas nameru nesto da prosirujes, onda je deklaracija interfejsa cist noise. Ako imam recimo funkciju koji kaze da prima interfejs, recimo neki Converter, i taj converter ima jednu implementaciju u celom projektu, i nikad nece imati vise od jedne, i to vazi za 95% interfejsa, onda je to nesnosni noise. Kada vidim da funkcija prima interfejs, gde se implementacija nalazi? Jel moram ja da ga implementiram? Pa cim si definisao kao interfejs onda dajes do znanja da bi trebalo da implementiras, ali posto to u stvari nije prava upotreba interfejsa, onda samo treba da ides i da pretrazujes projekat koja to klasa implementira interface ili da imas neki dependency injection container (opet silovanje, container koji uvek vraca istu implementaciju za isti interfejs, ali ono, mozda zatreba jednog dana....).
[ Branimir Maksimovic @ 02.12.2018. 03:34 ] @
Ne vidim kakve veze ima struktuirani type sa interfejsima ;)
Osim to da ti ne treba eksplicitna deklaracija interfejsa (kao recimo u slucaju C++ template-a) ;)
E sad sto se tice koriscenja generickih funkcija u lokalu, a i onih koje koriste interfejs, ne znam jel to zloupotreba ili ne u slucaju da ima samo jedan slucaj ;)
Tu mozes stvar gledati i tako da razbijanje koda na vise lokalnih f-ja nema smisla ;)

[ negyxo @ 02.12.2018. 07:58 ] @
Strukturalan type system ti omogucuje da lakse radis sa interfejsima. Na pocetku sam i rekao da zavisi i gde koristis interfejse. Opisao sam zasto u nominalnom interfejsi postanu noise (IoC style). Prostim prebrojavanjem, recimo u C# i u TypeScript, mogu da primetim da je upotreba interfejsa u TypeScript-u bar 10x veca (skoro da nema klasa). Da je to slucaj u C# - pa poludeo bi :) a opet, razlog zasto je to tako je u tome da bi mogao da "seces" i stvaras tipove kako ti je volja kada prosledjujes vrednosti.
[ jablan @ 02.12.2018. 11:18 ] @
Citat:
Nedeljko:
Da mi je znati šta je loše u uzimanju opšte poznatih primera.

Nisu u pitanju opšte poznati, već usiljeni primeri koji nemaju veze sa realnim modeliranjem. Čak ni kad dizajniraš program za zoološki vrt ili za veterinare, nećeš praviti klase Dog i Cat, već ćeš eventualno imati Pet i Owner.
[ Nedeljko @ 02.12.2018. 12:20 ] @
A kad praviš vidoje igru? Da li onda klase Dog i Cat imaju smisla?
[ jablan @ 02.12.2018. 15:56 ] @
Ne.
[ nkrgovic @ 02.12.2018. 16:23 ] @
Da li je neko od vas koristio ne lambda funckije vec lambda arhitekture, u smusli bilo da vam je neko pravio custom sistem koji dize kontejnere on-event kad se nesto desi na API gateway-u, bilo kao AWS Lambda? Ovakva paradigma je postala popularna, pre svega zbog cene jer je to jedini sistem gde se ne placa ni milisekund koriscenja resursa od onoga sto je potrebno za izvrsenje. Razlog zasto google kroz gloang, ili npr. node.js forsiraju funkcionalno programiranje je vezan pre svega za taj tzv serverless pristup, tj. duboke nivoe apstrakscije infrastrukture, gde dev team moze da se opet distancira od ops tima (da, da... idi mi - dodji mi, opet), i da opet svako radi svoj posao ;) .

Cena je glavni motivator cele price, to je sustina. A cena vuce formu (serverless), forma vuse strukturu (lambda), a sturktura vuce paradignu jezuka (funkcionalni).
[ Nedeljko @ 02.12.2018. 17:33 ] @
Citat:
jablan: Ne.

Pa, vidi, razne klase karaktera u vidoje igrama imaju različita ponašanja. Koliko ja znam, to se u vidoje igrama tako implementira.
[ Predrag Supurovic @ 02.12.2018. 18:41 ] @
Citat:
negyxo:
Ne, zadnjih par komentara se odnosi na to kako strukturalni type sistem ti omogucuje da implementiras interface on-the-fly.

Zloupotreba se odnosi na onaj deo koji sam opisao u drugom postu, kada uzmes i za svaku klasu namestis interface. To znaci, ako planiras da tvoj code koristis samo interno, i nema neki public deo, i nemas nameru nesto da prosirujes, onda je deklaracija interfejsa cist noise. Ako imam recimo funkciju koji kaze da prima interfejs, recimo neki Converter, i taj converter ima jednu implementaciju u celom projektu, i nikad nece imati vise od jedne, i to vazi za 95% interfejsa, onda je to nesnosni noise. Kada vidim da funkcija prima interfejs, gde se implementacija nalazi? Jel moram ja da ga implementiram? Pa cim si definisao kao interfejs onda dajes do znanja da bi trebalo da implementiras, ali posto to u stvari nije prava upotreba interfejsa, onda samo treba da ides i da pretrazujes projekat koja to klasa implementira interface ili da imas neki dependency injection container (opet silovanje, container koji uvek vraca istu implementaciju za isti interfejs, ali ono, mozda zatreba jednog dana....).



Pokušavam da razumem tvoj ugao gledanja ali mi baš ne ide. Možda zato što nemam neko isksutvo rada u C++ i Javi (kad god sam probao odbijao me je nesnosan utisak skučenosti i ograničenja).

Pazi, svaki pristup ima opravdanje jer da nema ne bi postojao. Svaki pristup može da se ne koristi, da se koristti, da se preterano koristi i da se koristi naopako. A to opet zavisi od ličnih afiniteta, navika, načina razmišljanja, umešnosti i iskustva i sličnog.

Meni je recimo "on the fly" (kreiranja tipova, strutkura, funckija...) naopak pristup (neću ići dotle da ga nazovem fašističkim ali ga smatram jednom od većih grozota) a ti ga voliš. Daleko bilo da ne koristim "dinamički" pristup. Nekad se on ne može izbeći i ume znatno da uporosti stvari ali u svemu treba imati mere.

Takođe tvoj omiljen pristup nasleđivanja više klasa meni ne leži (koncept mi je simpatičan ali mi ne pije vodu u realnoj primeni). Naravno da nisam ja u pravu kao što nisi ni ti upravu. Svako od nas treba da radi kako mu pogoduje. Klali bismo se samo ako bismo radili na istom projektu :)

Naravno da je pogrešno preterivati u svemu pa i u upotebi interfejsa. Interfejs se definiše kada je potreban i implementira onda kada je potreban. Niko tebe ne prisilajva da implementiraš odeđeni interfejs osim ako ne treba da komuniciraš sa nekom klasom koja zahteva određeni interfejs. Upravo taj interfejs omogućava da ta klasa komunicira sa tvojom klasom ne znajući o njoj ništa više od tog interfejsa. Interfejs upravo tome i služi, da definiše protokol po kome klase komuniciraju ne ulazeži u samu strukturu tih klasa.

Nije mi jasno na šta misliš kada kažeš da ti je problem da nađeš ko implementira neki interfejs. Nema šta ko da ga implementira, implementiraš ga ti na tvojoj klasi ako ona treba da komunicira sa drugom klasom preko tog interfejsa.

Često kada objašnajvam interfejse navodim primer iz prakse, primer sa komponetnama grafičkog intefejsa koje prikazuju tabele. To su na primer grid, combo box, list, box, meni i slične komponente.

Nisu one bez razloga napravljene uz upotrebu interfejsa (u C# to su konkretno IEnumerable i IEnumerator) jer na taj način je omogućeno da one prikažu bilo kakve podatke bez obira u kakvim su objektima. Dakle, one će prihvatiti i prikazati podatke koji imaju IEnumerable intefejs i neće uopšte ulaziti da li se radi o standardnoj tabeli, nekoji listi, koilekciji ili možda čak i sasvim custom klasi. Sve dok prosleđeni podatak ima implementiran interfejs podaci će biti prikazani u bilo kojoj grafičkoj komponenti koja prikazuje podtke koje su u nekakvom tabelarnom obliku.

Ne odnosi se iEnumerable samo na grafičke komponente. Recimo ako napraviš klasu koja implementira iEnumerable interfejs moći ćeš da je obrađuješ i sa foreach. Ako to ne uradiš, onda ćeš morati da protrčavaš kroz sve elemente u svojoj strukturi ručno, na neki svoj način.

Zaista ne vidim problem s aimplementacijominterfejsa. Njega implementiraš samo ako ti je potrebno. Niko te ne uslovljava da implementiraš interefejs ako se on neće koristiti. Implementacije interfejsa se nasleđuju tako da ako implementiraš interfejs na nekoj baznoj kasi sve klse koje su naslednici će takođe koristiti tu implementaciju.
[ negyxo @ 02.12.2018. 19:43 ] @
@Predrag

Upadas u "zamku" kao pre par godina kada smo diskutovali o interfejsima. Nije potrebno da diskutujemo o tome kako se interfejsi pravilno koriste, taj deo je jasan, ono sto izgleda nije jasno je kada se interfejsi svuda koriste da bi ti ceo code bio "decoupled", da bi ispunio neki design pattern. Sad, nema smisla da ti odgovaram na svaku recenicu, ako pokusas da razumes ovu prethodnu recenicu onda ce ti biti jasno zasto.
[ Predrag Supurovic @ 02.12.2018. 20:52 ] @
Ok ali ako ti pišeš kod onda valjda ti o tome odlučuješ i ne može ti programski jezik biti fašistički zbog toga što ima interfejse. Kako ćeš da ih koristiš to je tvoja stvar.

Što više slobode jezik daje to više "sra*a" mogu da se mašravi u njemu.

[ negyxo @ 02.12.2018. 23:07 ] @
Prvo, nisam ja pisao o tome sta je fasisticki a sta ne, dao sam samo svoj komentar po pitanju interfejsa i njihovo koriscenje.

Drugo, ja koristim interfejse na isti nacin kao sto si i sam opisao, i nemam problem sa zloupotrebom... ali, sta mislis sta se desi kada nisi ti vlasnik projekta, ne odlucujes ti sta ces pisati, ne radis samo ti, nego 10 programera i code nije trivijlan od par desetina fajlova? Jel sad mozes da zamislis situaciju zasto je bolno kada sve po automatizmi pokusvas da "decoupled-ujes"?

Trece, ne slazem se oko slobode - treba da je ima sto vise i da je jasno definisana. Ono sto "ti" kao programer treba da radis je da pises sto striktnije a ne jezik da bude striktniji, da te ogranicava u opsiu problema. Sad, ovo je jako tesko definisati da budem iskren. Neke slobode su jednostavno destruktivne (recimo promena vrednosti promenljivi, sad je malo integer, pa je malo string, pa je malo datetime itd), no u duhu slobode, treba ostaviti svakom izbor da ima nacin da podesi sta mu odgovara i to je to.
[ Predrag Supurovic @ 03.12.2018. 06:48 ] @
Citat:
negyxo: Prvo, nisam ja pisao o tome sta je fasisticki a sta ne, dao sam samo svoj komentar po pitanju interfejsa i njihovo koriscenje.


nisam ni miilsio na tebe, nego na taj pristup. Izvini ako nisam bio jasan.

Citat:

Drugo, ja koristim interfejse na isti nacin kao sto si i sam opisao, i nemam problem sa zloupotrebom... ali, sta mislis sta se desi kada nisi ti vlasnik projekta, ne odlucujes ti sta ces pisati, ne radis samo ti, nego 10 programera i code nije trivijlan od par desetina fajlova? Jel sad mozes da zamislis situaciju zasto je bolno kada sve po automatizmi pokusvas da "decoupled-ujes"?


Siguran sam da se svaki dugogodišnji programer sretao sa takvim stvarima, ali ne mislim da za to treba kriviti jezik nego onog ko je tako nešto napravio.

Na primer, mnogo ćeš pre nailaziti na gomilu svinjarija u jezicima koji dozvo9ljavaju "on the fly" kreiranje struktura, funkcija, ili čega već, nego u nekom jeziku koji ima interfejse. Pogledaj na primer JavaScript. Od ionako ružnog jezika napravili su papazjaniju upravo takvim pristupom.

Citat:

Trece, ne slazem se oko slobode - treba da je ima sto vise i da je jasno definisana. Ono sto "ti" kao programer treba da radis je da pises sto striktnije a ne jezik da bude striktniji, da te ogranicava u opsiu problema. Sad, ovo je jako tesko definisati da budem iskren. Neke slobode su jednostavno destruktivne (recimo promena vrednosti promenljivi, sad je malo integer, pa je malo string, pa je malo datetime itd), no u duhu slobode, treba ostaviti svakom izbor da ima nacin da podesi sta mu odgovara i to je to.


I ja se slažem da treba imati što više slobode, nego sam rekao da to nije garancija da će loši programeri pravili bolji kod nego najverovatnije baš obrnuto.

Kao i u mnogim drugim stvarima, veća sloboda teba onima koji znaju. Oni koji ne znaju je bolej da imaju u nekim stvariam vezane ruke da ne bi pravili budalaštine - dok ne nauče.
[ negyxo @ 03.12.2018. 07:46 ] @
Citat:

Siguran sam da se svaki dugogodišnji programer sretao sa takvim stvarima, ali ne mislim da za to treba kriviti jezik nego onog ko je tako nešto napravio.


Slazem se sa ovim kada se kaze uopsteno, to je jednostavno tako i da kazemo "normalno" stanje. No, kada govorimo o konkretnom slucaju, onda mozemo da uputimo i kritiku (sad da li je objektivna ili ne, to je sad vec u oko posmatraca :))

U slucaju interfejsa, bar za C#, ja mogu da kazem da su bespotreban konstrukt. Ne, ne njihovo koriscenje, nego konstrukt. Drugim recima, sve to mozes i sa klasama osim u jednoj stvari - a to je visestruko nasledjivanje. To je vestacki nametnuto, i ne mozes da promenis, i onda te jezik tera da koristis nesto jer nemas drugu opciju. Sad ti ces mozda reci da nemas potrebe sa visestrukim nasledjivanjem, ali to bas nije istina. Pogledaj kod sebe u code-u i pogledaj da li imas vise od jednog interface-a implementiranog u jednoj klasi. Posto si spominjao IEnumerable onda ti je poznat List<T>, kako izgleda ta klasa?

Code:

public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, IEnumerable, IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>


Zatim, pogledaj sledeci feature (bar je bio u najavi), default interface implementation. Pa kako je sada odjednom OK da imamo implementaciju u interfejsu? Ne, nikakva magicna igra reci ("znas, to je default metod") nece promeniti cinjenicu da ces sada da dobijes frankestajna samo zato sto nisi na prvom mestu odmah podrzao visestruko nasledjivanje. Bice interesatno sada kada pokusas da objasnis pocetnicima zasto da koriste interfejs sa default impelementacijom umesto klase :)

I da, sa ovim moze da se zivi, i kao sto rekoh negde ranije, meni je ovo manji problem nego non-null referentni tipovi.
[ negyxo @ 03.12.2018. 07:59 ] @
Citat:
Predrag Supurovic:
Na primer, mnogo ćeš pre nailaziti na gomilu svinjarija u jezicima koji dozvo9ljavaju "on the fly" kreiranje struktura, funkcija, ili čega već, nego u nekom jeziku koji ima interfejse. Pogledaj na primer JavaScript. Od ionako ružnog jezika napravili su papazjaniju upravo takvim pristupom.



Hehe, na ovo moram da odgovorim. Cak sta vise slazem se 100%, ali nisu svi jezici isti po tom pitanju, pa tako iako deluje isto, razlika je prilicno velika (probaj TypeScript, prijatno ces se iznenaditi).
[ Shadowed @ 03.12.2018. 09:44 ] @
Opet moram da izigravam drvenog advokata :))
Posto vidim da se ne kapirate...

Negyxo je jednostavnim primerom prikazao forsiranje interfejsa. Ocigledno je da tu nije potreban interfejs. Dovoljno funkcija trazi ili 4 parametra ili klasu/strukturu koja ih sadrzi. Ovakvo guranje interfejsa da bi se zadovoljio neki pattern ili "da bi bilo `aligned` sa ostatkom projekta" je primer cestih overarchitectured situacija sa projektima koje se srecu u enterprise aplikacijama. Ja sam se takvih stvari nagledao. Doduse, ne toliko ovih sa interfejsima ali to je samo jedan primer.

Razlog zasto je dao taj primer je navodjenje kako Go i Rust nemaju klase nego sve rade preko interfejsa (ne znam da li je tako, nisam ih koristio, ali je tako receno prethodno). To bi znacilo da ne samo da ces moci da imas situaciju kada se nepotrebno forsiraju interfejsi (kao u datom primeru) vec ce to u tim jezicima biti garantovano.


Bar sam ja tako razumeo.
[ Branimir Maksimovic @ 03.12.2018. 09:53 ] @
Go i Rust ne vezuju implementaciju interfejsa za strukturu. Znaci mozes implementacije razlicitih intefejsa staviti u razlicite fajlove a same
strukture takodje nemaju nikakve veze sa interfejsima...
[ jablan @ 03.12.2018. 10:28 ] @
Citat:
negyxo:
U slucaju interfejsa, bar za C#, ja mogu da kazem da su bespotreban konstrukt.


Samo ću ostaviti ovo ovde... :D

https://stackoverflow.com/ques...dant-with-multiple-inheritance
[ Branimir Maksimovic @ 03.12.2018. 10:35 ] @
Samo da dodam u Go i Rust-u interfejsi nisu nasledjivanje a samim tim nikakva multiple inheritance nije u pitanju. Interface je prosto protokol i nista vise.
Moze se implementirati interface kako za strukturu tako i za proste tipove.
[ negyxo @ 03.12.2018. 11:15 ] @
@jablan

Citat:

That said, I'm quite happy with single inheritance most of the time. Eric Lippert makes the point earlier in the same volume (p. 10) that the choice of single inheritance "... eliminates in one stroke many of the complicated corner cases..."


Haha, dobio si odmah odogovor sa "...ali I am quite happy" :D

Interesantno je da jedan broj koji se javio nije razumeo tvoje pitanje.
[ Predrag Supurovic @ 03.12.2018. 21:28 ] @
Citat:
negyxo:
U slucaju interfejsa, bar za C#, ja mogu da kazem da su bespotreban konstrukt. Ne, ne njihovo koriscenje, nego konstrukt. Drugim recima, sve to mozes i sa klasama osim u jednoj stvari - a to je visestruko nasledjivanje. To je vestacki nametnuto, i ne mozes da promenis, i onda te jezik tera da koristis nesto jer nemas drugu opciju. Sad ti ces mozda reci da nemas potrebe sa visestrukim nasledjivanjem, ali to bas nije istina. Pogledaj kod sebe u code-u i pogledaj da li imas vise od jednog interface-a implementiranog u jednoj klasi.


Mislim da sam samo jednom razmisljao o tome da bi mi trebalo višestruko nasleđivanje ali sam brzo odbacio tu ludu misao :)

Mešaš nasleđivanje i implementaciju. Nasleđuju se objekti, interfejsi se implementraju, to su potpuno različite stvari. Čak i da C# ima višestruko nasleđivanje to ne bi isključilo potrebu za interfejsima. Tek sa interfejsima objektno programiranje ima punu snagu.
[ negyxo @ 03.12.2018. 21:49 ] @
Da kojim slucajem C# ima visestruko nasledjivanje, interfejsi bi od mene dobili srednji prst :D

Mislim, vidis, i ti kazes nije to nasledjivanje nego implementiranje. Sve je to nepotreban noise. Sta je onda apstraktna klasa sa samo apstraktnim metodma? Jel se implementira ili se nasledjuje :) Mislim, to su samo reci, sustina je, da je interfejs samo jedan unapred definisan fixni contract, koji bas nema mnogo podesavanja. Klasa, sa svojim svim atributima i modifierma daleko vise ti omogucuje da fine-tuning-ujes sta ce da se nasledjuje.

BTW. Pogledaj jablanovo pitanje na SO da bi razumeo zasto interfejsi postoje.
[ dusans @ 03.12.2018. 22:14 ] @
Interfejsi formalno omogućavaju najstrože i najčistije vidove polimorfizma i enkapsulacije.
[ mjanjic @ 03.12.2018. 22:38 ] @
Par insteresantnih odgovora na: https://stackoverflow.com/ques...bstract-class-and-an-interface
i par odgovara sa tog linka:
From MSDN:
Citat:
By using interfaces, you can, for example, include behavior from multiple sources in a class. That capability is important in C# because the language doesn't support multiple inheritance of classes.
In addition, you must use an interface if you want to simulate inheritance for structs, because they can't actually inherit from another struct or class.

I relativno pojašnjeno, da ne prevodim:
Citat:
There are technical differences between Abstract Classes and Interfaces, that being an Abstract Class can contain implementation of methods, fields, constructors, etc, while an Interface only contains method and property prototypes. A class can implement multiple interfaces, but it can only inherit one class (abstract or otherwise).

However, in my opinion, the most important difference between Interfaces and Abstract Classes is the semantic difference.

An Interface defines what something can do (how it behaves), and an Abstract Class defines what something is.

Take for example IEnumerable, the semantic meaning behind this is that anything that implements IEnumerable is enumable, it doesn't mean that it's an enumeration, but that it can behave like one (can be enumerated).

Contrast that with the washing machine example, anything that inherits it is a type of washing machine. Anything that inherits it would be a type of washing machine, a top loader, or side loader, etc.

Instead, if you had an interface called ICanWash, which could contain a method called Wash. You could have various things implement ICanWash, be it a Person, an abstract washing machine class, etc, where the actual implementation does not matter, just you need to know that the behavior is that it can wash things.

In summary, classes define what something is, interfaces define what something can do.


U tom smislu, ne znam kod C++, nisam u njemu ništa radio od 2002. ili 2003. godine, ali mi se čini da ovo baš i ne važi za C++ jer kod njega ne postoji ključna reč za deklaraciju interfejsa kao npr. kod C#, pa odatle zabuna. Jednostavni zavisi od jezika do jezika.
[ Shadowed @ 03.12.2018. 22:50 ] @
Citat:
Predrag Supurovic:Čak i da C# ima višestruko nasleđivanje to ne bi isključilo potrebu za interfejsima. Tek sa interfejsima objektno programiranje ima punu snagu.

Ne bi iskljucilo potrebu za onim sto donose interfejsi. Medjutim, to bi moglo da se postigne sa cistim apstraktnim klasama (onim kod kojih su sve metode, propertiji i eventi apstraktni).Interfejs kao koncept bi ostao ali interface kao kljucna rec ne bi bila neophodna. Ne kazem da bi trebalo tako ali da bi moglo - moglo bi.

Edit: s druge strane, sad kad uvedu default implementacije u interfejse, skoro pa ce postici obrnuto - da apstraktne klase budu suvisne. Kazem skoro jer apstraktne klase mogu imati npr. implementirane protected clanove.
[ negyxo @ 04.12.2018. 03:54 ] @
^Upravo. Koncept bi bio isti, samo ne bi postojala ta rec ali bi sa MI mogao da odlucis kada je nesto za nasledjivanje a kada je samo potreban oblik, sa malo tweakovanja jezika, to bi bilo jako prosto, poput extends i implements u typescriptu. E sad u vecini slucajeva, ne treba ti nasledjivanje, treba ti nesto poput mixina (mislim da bi u ts-u bilo odlicno da su ubacili jos jednu opciju pored extends i implements, recimo "deep implements" ili tako nesto).
[ Nedeljko @ 05.12.2018. 11:44 ] @
Citat:
mjanjic: U tom smislu, ne znam kod C++, nisam u njemu ništa radio od 2002. ili 2003. godine, ali mi se čini da ovo baš i ne važi za C++ jer kod njega ne postoji ključna reč za deklaraciju interfejsa kao npr. kod C#, pa odatle zabuna. Jednostavni zavisi od jezika do jezika.

Ovaj deo nije tačan za C++:
Citat:
A class can implement multiple interfaces, but it can only inherit one class (abstract or otherwise).

C++ klasa može da nasledi proizvoljan broj klasa. Na primer:
Code (cpp):

class A
{
    ...
};

class B
{
    ...
};

class C : public A, public B
{
    ...
};
 

To je razlog zašto C++ nema ključnu reč za interfejse. Kad imaš višestruko nasleđivanje klasa (C++ i Python ga imaju), interfejsi su nepotrebni jer su specijalan slučaj klasa.
[ mjanjic @ 05.12.2018. 11:59 ] @
Pa i napomenuo sam da ne važi za C++ (bar nije važilo pre 15 godina, ne znam ove revizije 2014 i novije da li su unele neke novine), onaj drugi citat se mislim tamo na stackoverflow odnosio na prethodni, tj. na C#.
[ negyxo @ 06.12.2018. 21:32 ] @
@mjanjic
Htedoh da odgovorim na tvoj pretposlednji post ali usled obaveza nisam stigao...

Elem, to je prilicno dobar odgovor na SO zasto su "potrebni" interfejsi iz ugla nekog idealnog OOP modela... ali, nedostaje onaj praktican deo, sta se desi kada zelis da implementiras na isti nacin tu funkcionalnost? Da, zelis da ti je code decoupled, pa samim tim prebacujes funkcionalnosti u razlicite delove, ali kako to onda iskoristiti a da ne moras uporno da ponavljas code? Mislim da je ovo problem na koji dizajneri interfejsa nisu mislili ili su mislili da to nije neki issue na koji ce se ljudi zaliti (a kao sto vidimo, sa ovim defaults interface implementation upravo pokusavaju, ja bih rekao na polovican nacin, da rese).

Recimo, da vidimo iz ugla code-a, kako to izgleda:

Code:

interface ICanWash 
{
    void Wash();
    bool IsDirty;
}

class Person {
    string Name;
    Date Born;    
}

class Car {
    string Model;
    int Year;
}


Imamo dve klase, imamo jedan interfejs (contract) koji nam definise sta mozemo da radimo/implementiramo (ne nasledjujemo) sa tim objektima. Ako probamo da implementiramo:

Code:

class Person : ICanWash {
    string Name;
    Date Born; 
    bool IsDirty;

    Wash() {
       // do some common functionality
       IsDirty = false;
    }
}

class Car : ICanWash {
    string Model;
    int Year;
    bool IsDirty;

    Wash() {
        // do some common functionality
        IsDirty = false;
    } 
}


Iz ovog primera, vidimo da imamo redudantan code. Sta mozemo da radimo? Pa apsolutno nista, mozes common functionality da prebacis u neku common klasu i odatle implementiras interfejs (i opet imas redudantan code). Naravano, u ovom primeru bi mogli da namesitmo apstraktnu klasu i nasledimo je, ali to nije poenta, zato sto: prvo, zelimo da imamo cist OOP model, ne zelimo nasledjivanje, i drugo, ovaj primer nema u klasama Person i Car base klasu, da kojim slucajem ima, onda opet ne bi mogli da iskoristimo klasu.

E sad, kako bi code izlgedao sa klasom:


Code:

class CanWash {
   bool IsDirty;

    Wash() {
       // do some common functionality
       IsDirty = false;
    }
}

class Person : CanWash {
    string Name;
    Date Born;
}

class Car : CanWash {
    string Model;
    int Year;
}


Hm, iz mog ugla ovo je daleko elegantnije nego ovo sa interfejsima ali... imamo jedan problem, mi smo nasledili, tamo gde treba da implementiramo, opet nekako to nije to ali... kako se implementira interface, recimo u C#, a kako se nasledjuje klasa:

Code:

// interface implementation
class Car: ICanWash

// class inheritance
class Car: CanWash



WTF? Pa zar ovo nije igra reci onda? Nije naravno, onaj odgovor na SO nam govori suptilnu razliku.

OK, ali onda, trebalo je tu suptilnu razliku eksplicitno naglasiti, pa bi onda valjda i oni pure OOP concept zealoti bili zadovoljeni.

I, sad cu se osvrnuti na TypeScript. Nisam pratio razvoj TypeScripta, ali cini mi se da su tamo upravo ovo hteli da naglase, plus, imamo skoro proof-of-concept kako bi ovo moglo da funkcionise da su sve klase.

U TypeScriptu postoje dve kjlucne reci extends i implements, i to nas dovodi do:
- klasa moze da nasledi klasu, ali ne moze interface
- klasa moze da implementira interface
- klasa moze da "implementira" klasu
- interface moze da nasledi interface
- interface moze da "nasledi" klasu

i code:

Code:

interface ICanWash 
{
    void Wash();
    bool IsDirty;
}

class Person {
    string Name;
    Date Born;    
}

class Car {
    string Model;
    int Year;
}


ako pokusamo da implementiramo

Code:

class Person implements ICanWash {
    string Name;
    Date Born; 
    bool IsDirty;

    Wash() {
       // do some common functionality
       IsDirty = false;
    }
}

class Car implements ICanWash {
    string Model;
    int Year;
    bool IsDirty;

    Wash() {
        // do some common functionality
        IsDirty = false;
    } 
}



ako pokusamo da nasledimo:

Code:

class CanWash {
   bool IsDirty;

    Wash() {
       // do some common functionality
       IsDirty = false;
    }
}

class Person extends CanWash {
    string Name;
    Date Born;
}

class Car extends CanWash {
    string Model;
    int Year;
}



Voila! Ali smo prekrsili onaj koncept sa SO, mi smo nesto nasledili, umesto implementirali ali TypeScript dozvoljava da se klasa impelementira, u kom slucaju, se ne nosi default implementacija, nego se nosi samo njen implicitni "interface":


Code:

class Person implements CanWash {
    string Name;
    Date Born; 
    bool IsDirty;

    Wash() {
       // do some common functionality
       IsDirty = false;
    }
}

class Car implements CanWash {
    string Model;
    int Year;
    bool IsDirty;

    Wash() {
        // do some common functionality
        IsDirty = false;
    } 
}


Sto ce reci, da je isto kao da imamo i interface, jer TypeScript, iako postoji klasa CanWash, gleda samo fasadu te klase (interface) ne i implementaciju.

E sad, TypeScript, bas kao i C# i Java ne podrzava MI, pa samim tim, onda je uvek safe bet da se ide na interface, ali da koji slucajem podrzava, onda bi interface-i bili totalno bespotrebni. TypeScript ima mixine zato, ali kada bi otisli korak dalje, mixini bi mogli da se implementiraju kroz implements direktivu, tj. neku novu, kao sto sam spomenuo, "deep implements".


Code:


// Mora da se implementira CanWash, iako je CanWash klasa sa implementacijom, 
// jer smo rekli da hocemo fasadu te klase
class Person implements CanWash {
    string Name;
    Date Born; 
    bool IsDirty;

    Wash() {
       // do some common functionality
       IsDirty = false;
    }
}

// ne mora nista da se implementira, vec je implementirano sa "deep implements",
// ovo je razlicito od "extends" extends nasledjuje, "deep implements" implementira,
// deluje pomalo smesno, kada se gleda code, samo su reci razlicite, ali u runtime
// to bi se moglo manifestovati tako da kada ispitamo:
//    Persion is CanWash -> false
//    Persion is implements CanWash -> true
//
class Person deep implements CanWash {
    string Name;
    Date Born; 
}


Sorry na poduzem postu.

edit: typo, IsDirty

[Ovu poruku je menjao negyxo dana 07.12.2018. u 05:29 GMT+1]
[ mjanjic @ 06.12.2018. 23:23 ] @
OK, dosta korisnih info i primera, ovo su stvari na koje bi trebali budući juniori i seniori da obrte pažnju, a ne samo da misle da je bitno naučiti što više sintakse nekog jezika i znati uraditi nekoliko šablonskih primera.
Poznavanje stvari kao što je ovo o čemu si pisao kod OOP čini tu bitnu razliku između običnog kucača koda i IT inženjera.
[ Zlatni_bg @ 07.12.2018. 03:29 ] @
Zapravo, ovakvi postovi su ono sto nam nedostaje. Svaka cast i hvala.
[ negyxo @ 07.12.2018. 04:40 ] @
Samo da dodam jednu stvar, tj. ispravim sebe. U zadnjoj recenici u proslom postu sam rekao da bi mixini mogli kroz neki novi keyword da se implementiraju. To nije tacna definicija. Mixini bi i dalje imali ulogu, posto u dosta slucajeva zelimo on-the-fly da dodamo constraint na postojeci type, tako da cak i sa "deep implements" konstrukcijom ne bi iskljucili mixine iz upotrebe.
[ Branimir Maksimovic @ 07.12.2018. 05:02 ] @
Razlika izmedju interfejsa i klase je u tome sto interfejs nema member varijable. Upravo zato i ne postoji problem kod visestrukog nasledjivanja jer nema duplih podobjekata baznih klasa. Prosto.
Osim toga interfejs ne mora biti vezan za klasu/tip uopste kao kod Rust-a i Go-a.
[ negyxo @ 07.12.2018. 05:31 ] @
Mislis nema u nekim jezicima :)

I ono sto ne mogu da razumem vec u nekoliko tvojih postova - zasto je to u opste bitno?

Po meni samo dobijas manje fleksibilnosti. Mene kao programera zanima samo jedna, apsolutno jedna stvar kada treba da odlucim sta da uradim po pitanju nekog poziva - tip, oblik onoga sa cim baratam, pa sta god da je on ispod (struct, class, interface, trait)... iznedju ostalog ovo je i jedan od razloga zasto ne volim dinamicke jezike, jer moram da pretpostavljam sta je to sa cim baratam (moram test da pustim, da preturam po code-u) ne mogu da odlucim odmah u momentu dok pisem code.
[ Branimir Maksimovic @ 07.12.2018. 06:13 ] @
U jeziku u kom se interfejs zove nesto sto ima member varijablu, klasa nema nikakvog smisla. Elem tamo gde se nasledjuje iz interfejsa kako bi se izbegao diamond inheritance problem sigurno nema member varijable u interfejsu.
[ Predrag Supurovic @ 07.12.2018. 06:22 ] @
Citat:
negyxo: @mjanjic
Wash() {
// do some common functionality
IsDirty = false;
}


Mismil da si ovde napravi pogresnu pretpsotavku.

Ovde se ne radi o zajednickoj funkcionalnosti. Interfejs sluzi tome da se moze komunicirati sa raznorosnim klasama. u ovom slucaju pranje osobe i pranje auta su potpuno razliciti procesi ali imaju istu svrhu.

Ne mozes da proces pranja rešiš osnovnoj klasi pa da je osoba i auto naslede jer se oni ne peru na isti način.

Uloga interfejsa je upravo u tome da on odredi da i osoba i auto znaju da se operu i spoljna klasa ce samo da im kaze da se operu ne ulazeci u to kako se to pranje zaista izvodi.

[ negyxo @ 07.12.2018. 06:34 ] @
Diamond problem - interfejsi, resenje za problem koji nikad niste imali :D

Nope, ponovicu ono sto je Nedeljko rekao, interface je specijalan slucaj klase, nista vise (trait u Rust-u, isto specijalan slucaj).

@Predrag

Slazem se da svako treba da ima svoju implementaciju, ali tamo gde treba. Tamo gde ne treba, dolazimo do redudancije:

primer:

Code:

interface ICheckable {
    bool IsChecked();
    void Check();
    void Uncheck();
}

class Person : ICheckable...
class Car: ICheckable...


Obe klase moraju isti code da implementiraju. Recimo da imas neku listu, kojoj hoces da prikazes persons i cars, treba ti opcija da mozes da mozes da chekiras item. Nema smisla ovo da se ponavlja (naravno, ovo je za neke stvari OK, za neke ne zelis da "gadis" tip, pa koristis mixine :)).
[ mjanjic @ 07.12.2018. 14:59 ] @
Jedna stvar je šta teorija OOP kaže o korišćenju interfejsa i klasa, ali to ne mora imati veze sa onim što su autori određenog jezika hteli da postignu.

Na primer, kod TypeScript-a korišćenje klase umesto interfejsa za type-checking rezultuje u prevođenju u JS ogromnom razlikom - kad se koristi klasa, dobije se gomila koda, a kad se koristi interfejs, ne dobije se ništa jer JS je loosely-typed jezik tako da je interfejs poslužio samo za proveru pri kompajliranju u JS.

Razlikuje se od jezika do jezika, tako da princip koji važi u jednom jeziku ne mora važiti u drugom. Inače bi postojalo nekoliko programskih jezika kao pre 40 godina.
[ Branimir Maksimovic @ 20.04.2019. 10:25 ] @
Citat:
negyxo:
Diamond problem - interfejsi, resenje za problem koji nikad niste imali :D

Nope, ponovicu ono sto je Nedeljko rekao, interface je specijalan slucaj klase, nista vise (trait u Rust-u, isto specijalan slucaj).

@Predrag

Slazem se da svako treba da ima svoju implementaciju, ali tamo gde treba. Tamo gde ne treba, dolazimo do redudancije:

primer:

Code:

interface ICheckable {
    bool IsChecked();
    void Check();
    void Uncheck();
}

class Person : ICheckable...
class Car: ICheckable...


Obe klase moraju isti code da implementiraju. Recimo da imas neku listu, kojoj hoces da prikazes persons i cars, treba ti opcija da mozes da mozes da chekiras item. Nema smisla ovo da se ponavlja (naravno, ovo je za neke stvari OK, za neke ne zelis da "gadis" tip, pa koristis mixine :)).


Pa ne moraju. Stavis jednu da implementira pa je stavis kao agregat u obe i u implementaciji samo delegiras. Tako mora u rastu jer nema clasa. U ostalim takodje zato sto nema visestrukog nasledjivanja.
Interfejs nije klasa, kao sto ni klasa nije specijalan slucaj strukture. A mozemo reci da je sve specijalni slucaj vartijable ako cemo da idemo dalje ;)
[ mjanjic @ 20.04.2019. 13:37 ] @
Klasa je korisnički (definisan) tip podatka, a interfejs ti se u nekim jezicima provlači kao tip podatka.

Dakle, možeš imati IButton interfejs i Button klasu koja implementira taj interfejs, ali ćeš onda negde u nekom kontruktoru, koristeći DI, imati slučaj da ti je parametar kontruktora podatak tipa IButton, a ne tipa Button. Dakle, u tom smislu, IButton je takođe korisnički tip podatka, pa se smatra klasom, a i kod nekih jezika se koristi "class" eventualno uz prefiks "interface" (npr. kod C#).

Razlika između obične klase i interfejsa je očigledna, ali mnogima nije tako očigledna razlika između apstraktne klase i interfejsa. Kod nekih jezika interfejs ne može sadržati atribute, pa se može koristiti apstraktna klasa. Inače, apstraktna klasa i služi isključivo da se na jednom mestu deklarišu/definišu zajednički atributi i metode za više klasa, dok sama klasa nikad neće biti instancirana (npr. klasa "Vehicle" nema potrebe da instancira objekte, jer za to koristimo izvedene klase "Car", "Truck", itd.).
Ili, u realnom primeru, imamo apstraktnu klasu "Document" iz koje su izvedene klase "Report" i sl.

Glavna prednost interfejsa je što može da se sakrije implementacija, ali kod nekih drugih jezika je to moglo da se uradi i drugačije - npr. kod C++ drugom članu tima date samo .hpp fajl gde je deklaracija klase i gde se vidi šta koja metoda radi i koje nazive i parametre ima, ali se ne vidi KAKO je implementirana), kao što je opisano ovde: https://stackoverflow.com/ques...ss-in-c-into-hpp-and-cpp-files

U nekim drugim jezicima, kao kod C#, interfejsi se koriste npr. za DI i tako injektovan interfejs tretira se kao "service" (bar je tako kod .Core 2 Web API), tako da tu nije moguće interfejs tek tako zameniti apstraktnom ili običnom klasom.
[ Branimir Maksimovic @ 20.04.2019. 13:59 ] @
"Klasa je korisnički (definisan) tip podatka, a interfejs ti se u nekim jezicima provlači kao tip podatka."

Pa i interfejs je korisnicki definisan tip podatka.

Razlika je u tome sto class-a moze imati i metode i atribute a interfejs samo metode, tako da nema problema da se visestruko nasledjuju.
To je ujedno i svrha postojanja interfejsa.
[ mjanjic @ 21.04.2019. 01:05 ] @
Izvinjavam se za taj drugi deo rečenice, izgleda da sam nešto menjao pa mi je ostao takav, sad pojma nemam šta sam hteo da kažem, verovatno da se u nekim jezicima i interfejs tretira kao korisnički tip podatka (kao što sam naveo za IButton).


Kod nekih jezika i interfejs klasa može sadržati atribute, tako da nije to suštinska razlika.
Suštinska razlika je za šta se koristi interfejs, a za šta klasa (i apstraktna klasa).

Međutim, ako sa C pređe na C++, to i neće biti baš tako očigledno. Ali kod novijih jezika, a posebno framework-a koji favorizuju određene paterne (kao Dependency Injection, koji se negde smatra tehnikom, modelom, a neki ga nazivaju pattern-om), interfejs često mora da se koristi da bi se nešto odradilo na određen način.

Sa druge strane, Typescript ima interfejs koji praktično služi samo za 'type checking'.
[ negyxo @ 21.04.2019. 05:20 ] @
Citat:
Branimir Maksimovic:
Pa ne moraju. Stavis jednu da implementira pa je stavis kao agregat u obe i u implementaciji samo delegiras. Tako mora u rastu jer nema clasa. U ostalim takodje zato sto nema visestrukog nasledjivanja.
Interfejs nije klasa, kao sto ni klasa nije specijalan slucaj strukture. A mozemo reci da je sve specijalni slucaj vartijable ako cemo da idemo dalje ;)


Necu da delegiram ;)

Pa tako se upravo i radi, ako hoces bar malo redudanciju da smanjis ali kada ti jezik omogucava slobodu, onda imas jos manje posla (recimo, mogu da namestim mixin, i nemam onda nista da agregiram, samo definisem tip Checkable(Car) i imam isto to sa daleko elegantnijim code-om).
[ Branimir Maksimovic @ 21.04.2019. 06:25 ] @
"Kod nekih jezika i interfejs klasa može sadržati atribute, tako da nije to suštinska razlika."

Ako si mislio na C# to su isto metodi. U svakom slucaju klasican naziv za interfejs zna se sta je.
Jezici koji klase nazivaju interfejs nisu relevantni.
C++ nema interfejsa zato sto podrzava visestruko nasledjivanje i oni ne bi imali svoju svrhu.

"recimo, mogu da namestim mixin,"

Na sta mislis kada kazes mixin? Jedino na sta me asocira je D jezik gde iz stringa generises kod.
[ negyxo @ 21.04.2019. 07:16 ] @
Evo za typescript
[ Branimir Maksimovic @ 21.04.2019. 07:39 ] @
Pa dobro, to je jedan nacin da napravis neku genericku implementaciju za postojece klase za taj jezik. U Rustu, recimo, mozes da genericki implementiras interfejs za sve strukture, potom da dodas default implementaciju
gde trazis da se implementira samo jedna on n metoda interfejsa, itd.
Ono sto sam napisao stoji u slucaju da nema drugog resenja.
[ python_freak @ 21.04.2019. 19:56 ] @
Ja bih se bacio na C++ i osnove OOP-a. A posle toga imas veoma zanimljivu knjigu kao nastavak iz OO u dizajn paterne.
Cuvena knjiga Gang of Four Design Patterns: https://www.amazon.com/Design-...ofessional-ebook/dp/B000SEIBB8

Ako te mrzi da kupujes, mozes da je skines sa neta uz koji google-dork. Kucaj "GoF Design Patterns free pdf" i naci ces nesto.

EDIT:
O da i nemoj da zaboravis da pravis sopstvene projekte u kojima ces koristiti naucene stvari iznova i iznova i iznova.
To ti je najbolji nacin ucenja, posebno kada fejlujes 100 puta na tebi tesko shvatljivim stvarima pre nego sto dodjes do tacnog resenja a onda bacis sve cetri uvis, malo se odmoris i nastavis dalje sa malo vecim samopouzdanjem i osmehom na licu :D

[Ovu poruku je menjao python_freak dana 22.04.2019. u 00:23 GMT+1]
[ mjanjic @ 22.04.2019. 04:56 ] @
Pattern-e da uči tek na kraju, ne na početku. I pre toga dobro da nauči UML, nije pod obavezno, ali je korisno.

Ovako, može da nauči napamet šta je Factory i čemu služi, a da u praksi nikad ne prepozna gde treba da ga primeni, a gde je njegova primena suvišna.
[ Shadowed @ 22.04.2019. 07:20 ] @
Svakako. Dobar redosled je takodje bitan.

Citat:
mjanjic: Ovako, može da nauči napamet šta je Factory i čemu služi, a da u praksi nikad ne prepozna gde treba da ga primeni, a gde je njegova primena suvišna.

A takodje, moze da mu se desi i da sam dodje do tog (ili nekog drugog pattern-a) bez da je ucio o njemu. Ja sam imao situaciju da sam, kada sam saznao za design pattern-e i video neke primere, prepoznao dosta stvari koje sam vec radio na taj nacin pri cemu je meni je jednostavno bilo resenje nekih problema, nisam na to gledao kao na nesto standardizovano :)
[ Predrag Supurovic @ 23.04.2019. 02:38 ] @
Citat:
Shadowed
A takodje, moze da mu se desi i da sam dodje do tog (ili nekog drugog pattern-a) bez da je ucio o njemu. Ja sam imao situaciju da sam, kada sam saznao za design pattern-e i video neke primere, prepoznao dosta stvari koje sam vec radio na taj nacin pri cemu je meni je jednostavno bilo resenje nekih problema, nisam na to gledao kao na nesto standardizovano :)


Kom programeru se tako nešto nije desilo taj treba da menja profesiju :)

[ Shadowed @ 23.04.2019. 06:36 ] @
Pa, mislim da mnogima nije jer uce o patternima pre nego sto postoji prilika da do toga dodje. To ne znaci da su losi programeri vec da im je uskracena prilika da malo sami provaljuju stvari.