Ucząc się Celu C i czytając przykładowy kod, zauważam, że obiekty są zwykle tworzone przy użyciu tej metody:
SomeObject *myObject = [[SomeObject alloc] init];
zamiast:
SomeObject *myObject = [SomeObject new];
Czy jest ku temu powód, ponieważ przeczytałem, że są one równoważne?
objective-c
oop
willc2
źródło
źródło
Odpowiedzi:
Istnieje wiele powodów: http://macresearch.org/difference-between-alloc-init-and-new
Niektóre z nich to:
new
nie obsługuje niestandardowych inicjatorów (jakinitWithString
)alloc-init
jest bardziej wyraźny niżnew
Wydaje się, że ogólna opinia jest taka, że powinieneś używać wszystkiego, co ci odpowiada.
źródło
+newWithString:
, jeśli już to zrobiłeś-initWithString
. Jednak nie tak często. Osobiście zawsze używam,new
gdy wyznaczony inicjator jestinit
, po prostu taki krótki i słodki.+newWithString:
. To zrywa podział problemów. Bo kiedy i tak chcesz po prostu użyć-init
, nie ma powodu, by po prostu tego nie używać+new
.[[NSString alloc] initWithFormat:...]
i[NSString stringWithFormat:...]
oba są równoważne. Czy twierdzisz, że Apple naruszył podział problemów i nie powinien był tego w ten sposób wdrażać? (Uwaga: nie próbuję być protekcjonalny; chciałbym tylko uzyskać więcej informacji i wiedzieć, czy podążanie za przykładem Apple jest czasem złym pomysłem.)Bardzo stare pytanie, ale napisałem przykład dla zabawy - być może okaże się przydatny;)
W głównej funkcji obie instrukcje:
i
skutkuje tym samym wynikiem:
źródło
[[InitAllocNewTest alloc] init]
nie będzie się kompilować, dopóki nie będzie to miało[InitAllocNewTest new]
wpływu. (Przepraszamy za brak przerw w linii itp.)+new
jest równoważny+alloc/-init
zNSObject
implementacją Apple . Jest mało prawdopodobne, aby to się kiedykolwiek zmieniło, ale w zależności od poziomu paranoi dokumentacja Apple+new
wydaje się pozwalać na zmianę implementacji (i przełamanie równoważności) w przyszłości. Z tego powodu, ponieważ „jawność jest lepsza niż domniemanie” i dla ciągłości historycznej społeczność Celu-C zasadniczo unika+new
. Zazwyczaj można jednak zauważyć niedawnych użytkowników Java w Objective-C dzięki ich upartemu użyciu+new
.źródło
+new
istnieje już od czasów NeXT. Jeśli coś+new
jest oznaką kogoś, kto nauczył się objc dawno temu; Widzę wielu ludzi, którzy lubią język, a nawet piszą go od lat, ale wyraźnie po boomie na iOS, nie mają pojęcia, co+new
to znaczy. Po drugie, jak+new
to jest bardzo stare i od czasów NeXT, Apple byłoby całkiem szalone, aby zmienić go w sposób, który łamie stary kod, zwłaszcza biorąc pod uwagę, że ich własne podstawy kodu są prawdopodobnie zaśmiecone.new
idiom pochodzi z Smalltalk. Jest również używany w Ruby, a zarówno Objective-C, jak i Ruby czerpią wiele ze swojej składni i konwencji z Smalltalk.Często będziesz musiał przekazywać argumenty,
init
więc będziesz używał innej metody, takiej jak[[SomeObject alloc] initWithString: @"Foo"]
. Jeśli jesteś przyzwyczajony do pisania tego, masz w zwyczaju robić to w ten sposób, więc[[SomeObject alloc] init]
może to być bardziej naturalne[SomeObject new]
.źródło
Jedna krótka odpowiedź to:
źródło
Na marginesie, osobiście używam,
[Foo new]
jeśli chcę, aby coś w init zostało wykonane bez użycia jego wartości zwracanej w dowolnym miejscu. Jeśli[[Foo alloc] init]
nigdzie nie skorzystasz ze zwrotu , otrzymasz ostrzeżenie. Mniej więcej używam[Foo new]
dla oka.źródło
Spóźniłem się z tym, ale chcę wspomnieć, że to nowe jest w rzeczywistości niebezpieczne w świecie Obj-C ze Swift. Swift utworzy domyślną metodę inicjowania tylko wtedy, gdy nie utworzysz żadnej innej inicjalizacji. Wywołanie nowego w szybkiej klasie z niestandardowym inicjatorem spowoduje awarię. Jeśli użyjesz funkcji replace / init, kompilator prawidłowo narzeka, że init nie istnieje.
źródło
Jeśli new wykona za ciebie zadanie, spowoduje to również, że twój kod będzie nieco mniejszy. Jeśli inaczej byś zadzwonił
[[SomeClass alloc] init]
w wielu różnych miejscach kodu, utworzysz Hot Spot w implementacji new - czyli w środowisku wykonawczym objc - co zmniejszy liczbę braków w pamięci podręcznej.W moim rozumieniu, jeśli potrzebujesz użyć niestandardowego użycia inicjalizatora
[[SomeClass alloc] initCustom]
.Jeśli nie, użyj
[SomeClass new]
.źródło
init
funkcję i użyj jej.[[SomeClass alloc] init];
Jeśli potrzebujesz parametrów, nadal nigdy nie rób czegoś takiego[[SomeClass alloc] initWith:...];
. Na koniec, jeśli zastąpiszinit
funkcję niestandardową implementacją, możesz wywołać obiektnew
po utworzeniu i nadal będzie on wywoływał niestandardowąinit
implementację.