Nauczyłem się C # przez ostatnie sześć miesięcy i teraz zagłębiam się w Javę. Moje pytanie dotyczy tworzenia instancji (naprawdę w każdym języku), a więcej: zastanawiam się, dlaczego to zrobili w ten sposób. Weź ten przykład
Person Bob = new Person();
Czy istnieje przyczyna dwukrotnego określenia obiektu? Czy kiedykolwiek będzie something_else Bob = new Person()
?
Wydaje się, że gdybym postępował zgodnie z konwencją, byłoby to bardziej:
int XIsAnInt;
Person BobIsAPerson;
A może jeden z nich:
Person() Bob;
new Person Bob;
new Person() Bob;
Bob = new Person();
Myślę, że jestem ciekawy, czy istnieje lepsza odpowiedź niż „po prostu tak się to robi”.
java
c#
object-oriented
Jason Wohlgemuth
źródło
źródło
LivingThing
? Mógłbyś pisaćLivingThing lt = new Person()
. Poszukaj dziedziczenia i interfejsów.Person Bob
deklaruje wywoływaną zmienną typu „referencja doPerson
”Bob
.new Person()
tworzyPerson
obiekt. Odnośniki, zmienne i obiekty to trzy różne rzeczy!var bob = new Person();
?Person Bob();
jest możliwe w C ++ i oznacza prawie to samo, coPerson Bob = Person();
Odpowiedzi:
Tak, z powodu dziedziczenia. Gdyby:
Następnie:
Bob też jest osobą, a na golly, nie chce być traktowany inaczej niż ktokolwiek inny.
Co więcej, możemy wyposażyć Boba w super moce:
Tak więc, na golly, nie będzie on traktowany inaczej niż jakikolwiek inny moderator. I lubi przekradać się po forum, aby wszyscy byli w kontakcie podczas incognito:
Następnie, gdy znajduje biedny 1. plakat, zrzuca pelerynę niewidzialności i rzuca się.
A potem może zachowywać się niewinnie i tak dalej:
źródło
enum
.Weźmy pierwszy wiersz kodu i sprawdźmy go.
Pierwszy
Person
to specyfikacja typu. W języku C # możemy zrezygnować z tego, po prostu mówiąca kompilator wyprowadzi typ zmiennej Bob z wywołania konstruktora
Person()
.Ale możesz napisać coś takiego:
W przypadku, gdy nie wypełniasz całej umowy API Person, ale tylko umowę określoną przez interfejs
IPerson
.źródło
IPerson
przykład w moim kodzie, aby upewnić się, że przypadkowo nie użyję żadnych prywatnych metod podczas pisania kodu, który powinien być kopiowany / wklejalny do innejIPerson
implementacji.internal
?private
ma znaczenie: metody fabryczne, które są częścią instancji klasy, są tworzone. W mojej sytuacji dostęp do wartości prywatnych powinien być wyjątkiem, a nie normą. Pracuję nad kodem, który długo mnie przeżyje. Jeśli zrobię to w ten sposób, nie tylko raczej nie będę samodzielnie stosować żadnych prywatnych metod, ale kiedy następny programista skopiuje / wklei to kilkadziesiąt miejsc, a programista po tym skopiuje je, zmniejsza szanse, że ktoś zobaczy okazję stosować metody prywatne jako „normalne” zachowanie.Ta składnia jest prawie spuścizną po C ++, która, nawiasem mówiąc, ma zarówno:
i
Pierwszy tworzy obiekt w bieżącym zakresie, drugi tworzy wskaźnik do obiektu dynamicznego.
Zdecydowanie możesz
something_else Bob = new Person()
Robisz tutaj dwie różne rzeczy, określając typ zmiennej lokalnej
nums
i mówisz, że chcesz utworzyć nowy obiekt typu „Lista” i umieścić go tam.C # w pewnym sensie zgadza się z tobą, ponieważ przez większość czasu typ zmiennej jest identyczny z tym, co wstawiasz, stąd:
W niektórych językach starasz się nie podawać typów zmiennych jak w F # :
źródło
new std::pair<int, char>()
, członkowiefirst
isecond
para mają automatyczny czas przechowywania, ale prawdopodobnie są przydzielani na stercie (jako członkowie obiektu dynamicznego przechowywaniapair
).Istnieje ogromna różnica między
int x
iPerson bob
.int
Toint
jestint
i musi być zawszeint
i nigdy nie może być nic innego niżint
. Nawet jeśli nie zainicjujesz tego,int
kiedy go deklarujesz (int x;
), nadal jestint
ustawiony na wartość domyślną.Person bob
Jednak kiedy deklarujesz , istnieje duża elastyczność co do tego, do czego nazwabob
może się odnosić w danym momencie. Może odnosić się doPerson
lub może odnosić się do innej klasy, np.Programmer
Pochodzącej zPerson
; może nawet byćnull
, nie odnosząc się do żadnego przedmiotu.Na przykład:
Projektanci języka z pewnością mogliby stworzyć alternatywną składnię, która osiągnęłaby to samo, co
Person carol = new Person()
w przypadku mniejszej liczby symboli, ale nadal musieliby na to pozwolićPerson carol = new Person()
(lub wprowadzić dziwną regułę, czyniącą ten jeden z czterech powyższych przykładów nielegalnym). Bardziej zależało im na utrzymaniu prostoty języka niż na pisaniu wyjątkowo zwięzłego kodu. Mogło to wpłynąć na ich decyzję o niepodawaniu krótszej składni alternatywnej, ale w każdym razie nie było to konieczne i nie podali jej.źródło
Te dwie deklaracje mogą być różne, ale często są takie same. Typowy, zalecany wzorzec w Javie wygląda następująco:
Te zmienne
list
imap
są uznane za pomocą interfejsówList
iMap
gdy kod instancję konkretne implementacje. W ten sposób reszta kodu zależy tylko od interfejsów i łatwo jest wybrać inne klasy implementacji do utworzenia, na przykładTreeMap
, ponieważ reszta kodu nie może zależeć od żadnej częściHashMap
interfejsu API, która znajduje się pozaMap
interfejsem.Innym przykładem, w którym oba typy się różnią, jest metoda fabryczna, która wybiera określoną podklasę do utworzenia instancji, a następnie zwraca ją jako typ podstawowy, więc osoba dzwoniąca nie musi znać szczegółów implementacji, np. Wybór „polityki”.
Wnioskowanie typu może naprawić redundancję kodu źródłowego. Np. W Javie
zbuduje odpowiedni rodzaj Listy dzięki wnioskowaniu o typ i deklaracji
W niektórych językach wnioskowanie typu idzie dalej, np. W C ++
źródło
bob
, nieBob
. Pozwala to uniknąć wielu niejasności, np. Package.Class vs. Class.variable.clazz
.clazz
jest używany, ponieważclass
jest słowem kluczowym, więc nie może być użyty jako identyfikator.Class
jest doskonale poprawnym identyfikatorem.cLaSs
,cLASS
icLASs
.Słowami laika:
var = new Process()
nie deklarujesz zmiennej jako pierwszej.źródło
Chodzi również o poziom kontroli nad tym, co się dzieje. Jeśli deklaracja obiektu / zmiennej automatycznie wywołuje konstruktor, na przykład if
był automatycznie taki sam jak
wtedy nigdy nie byłoby możliwe użycie (na przykład) statycznych metod fabrycznych do tworzenia instancji obiektów zamiast domyślnych konstruktorów, to znaczy, że czasami nie chcesz wywoływać konstruktora dla nowej instancji obiektu.
Ten przykład wyjaśniono w „ Skutecznej Javie Joshua Blocha ” (dość ironicznie, jak w punkcie 1!)
źródło