Kto z was słyszał, że Java nie jest prawdziwym językiem OOP *dlatego*, że posiada prymitywy?

0

Jeśli wpiszemy w google "why is java not oop" albo "why is java not pure oop" albo "why is java not 100% oop", najpewniej dostaniemy odpowiedź "dlatego że zawiera prymitywne typy danych jak int, bool, float". Ile z was o tym słyszało i się z tym zagadza?

PS: Ja może od siebie dodam że uważam że Java nie jest 100% językiem OOP, ale nie dlatego że posiada prymitywy.

2

Spotkałem się, ale jest bardzo wąskie pojmowanie OOP ala "wszystko musi być obiektem".

Bardziej niż primitywy martwią mnie statyczne pola i metody - toż to funkcje i zmienne globalne znane z C! A zaraz po tym jest null który również nie jest obiektem (a mógłby być).

6

Tylko Smalltalk był pradziwie obiektowy. I może Ruby. Jarek Pałka kiedyś wspominał (powołując się na definicję twórców Smalltalka) że język statycznie typowany z definicji nie może być OOP. Co mnie jeszcze bardziej utwierdziło w przekonaniu że należy być jaknajdalej od OOP

8

Kiedyś o tym myślałem, ale już nie zaprzątam sobie głowy głupotami, które nie mają znaczenia. W Javie jak i w C można pisać obiektowo, przy czym w Javie jest to łatwiejsze i chwała za to. Jaki sens myśleć czy to język OOP czy nie...

0

Idac tym tokiem myslenia to Java jest jezykiem funkcyjnym bo ma lambdy?

2

Lambdy z Javy 8 to "tylko" cukier składniowy na klasy anonimowe, które były dostępne od Javy 1.1. Chociaż z drugiej strony te wygenerowane w locie klasy są lżejsze niż klasy anonimowe, więc nie jest to 1:1 porównanie.

Podstawą programowania funkcyjnego jest niemutowalność i unikanie efektów ubocznych. Lambdy są w praktyce niezbędnym narzędziem, bo pozwalają na zwięzłe przetwarzanie niemutowalnych obiektów, ale jak ktoś byłby zawzięty, to lambdy mógłby zastąpić klasami i tak się to w Javie < 8 robiło.

Co do:

Java nie jest 100% językiem OOP, ale nie dlatego że posiada prymitywy

To szykuje się pewna zmiana: http://openjdk.java.net/jeps/402 (JEP 402: Unify the Basic Primitives with Objects (Preview)). Nagle kod typu 5 instanceof Object skompiluje się i da true. Jakoś nie widzę w tym rewolucji (zwłaszcza, że na samym początku generyki na prymitywach dalej nie będą działać). Znaczącym postępem jest za to wynikające z primitive classes spłaszczenie obiektów i unikanie narzutu na nagłówki obiektów i zredukowanie pointer chasing. C# ma to (spłaszczenie itd) od dawna pod postacią struct, ale c#owe struct może być mutowalne (co samo w sobie jest podobno antywzorcem).

1

J.w jezykow prawdziwie obiektowych jest bardzo malo. O wiele wiecej jest "zorientowanych obiektowo".
Gdyby Java byla prawdziwie obiektowa to moze nie trzeba by bylo definiowac potworkow w rodzaju OptionalInteger lub IntToLongFunction.

Trzeba orac tym co jest bo te wszystkie jezyki pure sa mniej lub bardziej niszowe, chyba ze chodzi o programowanie hobbystyczne, wtedy programowanie nawet w Neptune moze byc fajne.

2

Ale to chyba dobrze, jak coś nie jest OOP, nie?

garść cytatów sławnych i mądrych

3

Ten dylemat z pytania z tego tematu to w ogóle trąci wypaczonym pojęciem obiektowości typu: x jest obiektem wtedy i tylko wtedy gdy x instanceof Object się kompiluje i zwraca true. To jest bardzo prostackie podejście i zupełnie nie o to chodzi w OOPie. Potem mamy "obiekty bez stanu" (np. typowy Comparator nie jest obiektem w sensie OOPowym, bo nie ma stanu, a tylko metody), albo "obiekty bez zachowania" (np. typowe DTO ma stan, a nie ma żadnych swoich metod, więc nie jest obiektem w sensie OOPowym, a raczej np. strukturą), które nie budzą żadnych podejrzeń OOPowych "purystów".

10

Lepiej się w ogóle nad tym nie zastanawiać i po prostu nie pisać w tej Javie. Jest tyle innych języków, że naprawdę nie ma co być masochistą xD

A w Javie tworzy się dużo pseudoobiektowego kodu, np. robienie getterów i setterów do wszystkiego i myślenie, że na tym polega OOP, żeby zrobić głupi pojemnik na dane + gettery i settery xD) albo podniecanie się wzorcami projektowymi, które w innych językach albo nie są potrzebne, albo można je dużo prościej zaimplementować.

4

Zrobiłbym krok wstecz i zapytał: „i co z tego?” xD

3

A w Javie tworzy się dużo pseudoobiektowego kodu, np. robienie getterów i setterów do wszystkiego i myślenie,

Co ma to do Javy? W C# się tak nie robi? To że ktoś nie umie programować obiektowo nie wynika że Java nie wspiera OOP. Są na tym forum programiści którzy klepią obietkowo w Javie

albo podniecanie się wzorcami projektowymi, które w innych językach albo nie są potrzebne, albo można je dużo prościej zaimplementować.

Tak, masz racje, dlatego powstaja takie prezentacje ;):

Zgadzam się z tobą, te rozwlekłe gettery i settery zaśmiecają kod.

Nie zanotowałem. ;]

 public record StartPlayingTrackEvent(Track track) {}
 eventBus.post(new StartPlayingTrackEvent(currentTrack));
  
  @Subscribe
  @SuppressWarnings("unused")//żeby IntelliJ mi na szaro nie podkreślał. Będzie działać bez.
  public void onStartPlayingTrackEvent(StartPlayingTrackEvent event) {
    playlistView.getSelectionModel().select(event.track());
  }

0

@Wibowit: Czytałeś może "Elegant Objects" Yegora Bugayenko?

0

@Wibowit: W aplikacji prawdziwie OOP, nadal warto mieć jedną klasę na jeden plik?

3

W aplikacji prawdziwie OOP, nadal warto mieć jedną klasę na jeden plik?

To zależy. Czasami tak, a czasami nie. Zresztą nawet rekordy w Javie można deklarować na poziomie metody :P IMO akurat trzymanie się takiego podejścia jedna klasa jeden plik jest trochę niepotrzebne często i niepotrzebnie mnoży byty.

0

Nie czytałem, ale czytałem za to jego posty na blogu. Ma podejście dość dogmatyczne, a to nie sprzyja znajdowaniu praktycznych rozwiązań.

Albo język jest obiektowy, albo nie jest. To czy obiektowe języki są użyteczne to zupełnie inna rozmowa. To czy programowanie obiektowe jest użyteczne czy jednak jest największym buzzwordem w historii informatyki to też zupełnie inna rozmowa

1

@TomRiddle:
Filozoficzne pytanie :] Jeśli robię coś co jest typowo obiektowe, czyli ma stan i zachowanie, to zwykle robię to w oddzielnym pliku. Z drugiej strony takie DTOsy nieraz pakuję hurtem w jednym pliku, bo pojedyncza case classa w Scali jest krótka i zwykle nie opłaca się robić osobnego pliku. Trzeba tylko pamiętać, żeby mieć sensowny namespace, a nie naśmiecone dziesiątki typów bezpośrednio w jednym package. Z tym, że DTOsy to przecież nie są pełnoprawne obiekty. Nigdy nie dążyłem do pisania w 100% obiektowo, więc nie mam z tym doświadczeń.

@KamilAdam
Hmm, a czy jest jakiś praktyczny język w 100% funkcyjny? Czy monada IO jest 100% funkcyjna? Efekt uboczny opakowany w monadę IO dalej jest efektem ubocznym, tyle że wykonywanym przez specjalnego interpretera monad IO. Kompozycja monad IO jest owszem czysto funkcyjna, ale ich interpretacja już nie. Stąd, jeśli zaczynamy kopać mocno i podchodzić do tematu dogmatycznie, to wpadamy w rabbit hole i wychodzą dziwne rzeczy. Można stworzyć np. czysto funkcyjną funkcję typu (World, String) -> World, która wypisuje stringa na ekran poprzez przerobienie danego World bez stringa na ekranie, na World ze stringiem na ekranie. To byłoby skrajnie niepraktyczne, ale za to pod wszelakimi względami czysto funkcyjne. W językach ogólnego przeznaczenia gdzieś tam abstrakcje zaczynają się sypać i trzeba postawić granicę.

2

Swoją drogą à propos Scali to gdzieś przeczytałem że aktorzy Akki to przykład prawdziwego OOP - mają wewnętrzny stan i komunikują się między sobą tylko za pomocą wiadomości :)

2
Aleksander32 napisał(a):

Swoją drogą à propos Scali to gdzieś przeczytałem że aktorzy Akki to przykład prawdziwego OOP

System aktorów był inspirowany bezpośrednio Smalltalkiem.
Podobno jeden programista rok czekał na komputer który uciągnie Smalltalk. Czekając najpierw napisał wszystkie message przesyłane między obiektami w Smalltalku. Potem dalej czekając opisał flow między messagami, ale w Prologu. Gdy już dostał komputer przepisał interpreter flow z Prologa do C. I tak, według legendy, powstał Erlang i jego system aktorów

2

OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things
:)

2

@Wibowit:

Hmm, a czy jest jakiś praktyczny język w 100% funkcyjny? Czy monada IO jest 100% funkcyjna?

Odpowiedź jest dość prosta - monada IO jest funkcyjna i czysta. Tak długo jak w kodzie nigdzie tej monady nie wykonujesz (unsafePerformIO czy coś w tym stylu).
Stąd zasadzniczo Haskell jest czysty i funkcyjny - bo twój kod jest czysty. Runtime pod spodem bierze na siebie wszytkie nieczystości.

Scala po dodaniu odpowiednich bibliotek i narzuceniu jakiegoś reżimu (linter) też może być 100% funkcyjna. (ale po prawdzie jeszcze nie widziałem w scali lintera, który by mnie w 100% zabezpieczył przed efektami ubocznymi).

0

Bycie językiem obiektowym (czy też zorientowanym obiektowo) to bardzo niejasne określenie (p.niżej). Obiektowość (języka) to paradygmat (który już jest zdefiniowany lepiej), a za język zorientowany obiektowo (raczej niż: obiektowy) zwykle uważamy taki, który ma mechanizmy językowe ułatwiające zorientowane obiektowo podejście do programowania. Java (bez wątpienia) ma takie mechanizmy, podobnie jak C++, Smalltalk, Python, Ruby, Rust i wiele innych. Ale samo programowanie zorientowane obiektowo jest przecież możliwe w innych językach (od asemblera po Haskella).

KamilAdam napisał(a):

Albo język jest obiektowy, albo nie jest.

Niby tak, ale co świadczy o obiektowości języka? Czy wystarczy, że ma mechanizmy (czyli: realizuje wspomniany paradygmat obiektowy), o których wyżej pisałem? Wtedy łapią się wszystkie powyższe i wiele innych. Czy też musi mieć tylko i wyłącznie mechanizmy obiektowe (nie dopuszcza innych paradygmatów albo je bardzo utrudnia)? Ale wtedy jest to język raczej ubogi i pewnie w dzisiejszych czasach dość niszowy/akademicki (Smalltalk?)...

TomRiddle napisał(a):

PS: Ja może od siebie dodam że uważam że Java nie jest 100% językiem OOP, ale nie dlatego że posiada prymitywy.

A czemu? :)

KamilAdam napisał(a):

[...] że język statycznie typowany z definicji nie może być OOP.

W jaki sposób obiektowość wyklucza się ze statycznym typowaniem?

0

Jak dla mnie Python przez brak normalnej enkapsulacji jest mniej obiektowy niż Java.

0

@jarekr000000 mnie ubiegł, ale i tak napiszę swoje. :)

Wibowit napisał(a):

Hmm, a czy jest jakiś praktyczny język w 100% funkcyjny? Czy monada IO jest 100% funkcyjna? Efekt uboczny opakowany w monadę IO dalej jest efektem ubocznym, tyle że wykonywanym przez specjalnego interpretera monad IO. Kompozycja monad IO jest owszem czysto funkcyjna, ale ich interpretacja już nie. Stąd, jeśli zaczynamy kopać mocno i podchodzić do tematu dogmatycznie, to wpadamy w rabbit hole i wychodzą dziwne rzeczy. Można stworzyć np. czysto funkcyjną funkcję typu (World, String) -> World, która wypisuje stringa na ekran poprzez przerobienie danego World bez stringa na ekranie, na World ze stringiem na ekranie. To byłoby skrajnie niepraktyczne, ale za to pod wszelakimi względami czysto funkcyjne. W językach ogólnego przeznaczenia gdzieś tam abstrakcje zaczynają się sypać i trzeba postawić granicę.

W sensie praktycznym @Wibowit ma rację, ale wygląda mi to na niezrozumienie monad (nie, żeby ktoś je w ogóle rozumiał :))... Zarówno monada IO jak i zabawy w stylu (World, String) -> World (które w językach funkcyjnych też miały jakieś przykłady, ale nie pamiętam już gdzie) są przykładami podejścia czysto funkcyjnego (tyle, że monady są wygodniejsze programistycznie) -- bo to podejście jest akurat dobrze zdefiniowane matematycznie (w przeciwieństwie do podejścia obiektowego).

4
Aleksander32 napisał(a):

Jak dla mnie Python przez brak normalnej enkapsulacji jest mniej obiektowy niż Java.

Python ma normalną enkapsulację -- nie ma kontroli dostępu. :) Ale to nie ma nic wspólnego z obiektowością.

1
jarekr000000 napisał(a):

@Wibowit:

Hmm, a czy jest jakiś praktyczny język w 100% funkcyjny? Czy monada IO jest 100% funkcyjna?

Odpowiedź jest dość prosta - monada IO jest funkcyjna i czysta. Tak długo jak w kodzie nigdzie tej monady nie wykonujesz (unsafePerformIO czy coś w tym stylu).

I ponieważ IO jest tylko deklaratywnym opisem efektu, ten opis można dalej zgubić i wtedy efekt się nie wykona (o czym dowiedziałem się przypadkiem przy błędnym łączeniu monad). Dla wyjaśnienia o co mi chodzi kod:

main = giveUpA (print "Hello, Wibowit!") (print "Hello, world!")

giveUpA :: IO () -> IO () -> IO ()
giveUpA a b = b

A wynik to "Hello, world!" czyli udało się "zgubić" pierwsze IO ()

0

Monada w wątku o OOP. Codziennie czlowiek sie czegos uczy...

0
koszalek-opalek napisał(a):
TomRiddle napisał(a):

PS: Ja może od siebie dodam że uważam że Java nie jest 100% językiem OOP, ale nie dlatego że posiada prymitywy.

A czemu? :)

No gdyby to był powód, to rozwiązanie byłoby bardzo proste: Nie używaj prymitywów, i bam. Obiektowy kod w Javie. Uważam, że język może mieć elementy: "Czysto OOP" + "Nieczysto OOP" i nadal być OOP.

Głównym powodem, moim zdaniem czemu Java nie uchodzi za Pure OOP język jest brak wielodziedziczenia i to że nie można nadpisać Stringa, Integera, etc. i żeby pisać 100% należałoby zrobić swoje typy String, Integer które enkapsulują te Javowe, ale wtedy można standardową bibliotekę Javy wrzucić do kosza.

0
jarekr000000 napisał(a):

@Wibowit:

Hmm, a czy jest jakiś praktyczny język w 100% funkcyjny? Czy monada IO jest 100% funkcyjna?

Odpowiedź jest dość prosta - monada IO jest funkcyjna i czysta. Tak długo jak w kodzie nigdzie tej monady nie wykonujesz (unsafePerformIO czy coś w tym stylu).
Stąd zasadzniczo Haskell jest czysty i funkcyjny - bo twój kod jest czysty. Runtime pod spodem bierze na siebie wszytkie nieczystości.

To branie na siebie wszystkich nieczystości jest właśnie tym kontrowersyjnym elementem. Dzięki możliwości uruchamiania efektów ubocznych z monad IO (obojętne jakim tam mechanizmem) mogę dowolny program imperatywny przenieść 1:1 do kodu opartego na monadach IO. Dla przykładu zamiast:

var x = 5
for (_ <- 0 to 3) x += 1

mogę zrobić coś a'la (scalowa składnia monadyczna, a więc trochę brzydsza niż haskellowa):

for {
  xRef <- IO.mutableRef[Int]()
  _ <- (0 to 3).map(_ => xRef.transform(_ + 1)).sequence
} yield ()

Analogicznie dla bardziej skomplikowanych przypadków.

2

@Wibowit:
Wiesz, że napisałeś kod bez efektów ubocznych :-).
Nie płakałbym nad tym, że da się w fp pisać kod prawie jak imperatywny:

  1. wymaga to pewnej ceremonii (i dobrze)
  2. czasem się przydaje
  3. te mutableRef jednak zwykle zachowują się lepiej przy dostępie z wielu wątków (tu oczywiście zależy od konkretnej biblioteki). (czyli w twoim przykładzie x = x+1 byłby atomowy w prawie każdej bibliotece do IO).

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