Niedawno kupiłem komputer Mac i używam go głównie do programowania w języku C # w ramach VMWare Fusion. Przy wszystkich fajnych aplikacjach na Maca zacząłem myśleć o Xcode czającym się po jednym kliknięciu instalacji i uczącym się Objective-C.
Składnia między tymi dwoma językami wygląda bardzo różnie, prawdopodobnie dlatego, że Objective-C ma swoje korzenie w C, a C # ma swoje korzenie w Javie / C ++. Ale można się nauczyć różnych składni, więc powinno być OK.
Moim głównym zmartwieniem jest praca z językiem i to, czy pomoże to stworzyć dobrze skonstruowany, czytelny i elegancki kod. Naprawdę lubię funkcje takie jak LINQ i var w C # i zastanawiam się, czy w Objective-C są odpowiedniki lub lepsze / różne funkcje.
Jakie funkcje językowe będę tęsknić za rozwijaniem w Objective-C? Jakie funkcje zyskam?
Edycja: Porównania ram są przydatne i interesujące, ale tak naprawdę to pytanie dotyczy porównania języków (częściowo moja wina, że pierwotnie oznaczałem .net
). Przypuszczalnie zarówno Cocoa, jak i .NET to bardzo rozbudowane frameworki same w sobie i oba mają swój cel - jeden jest przeznaczony dla Mac OS X, a drugi dla systemu Windows.
Dziękujemy za dotychczas przemyślane i rozsądnie wyważone punkty widzenia!
źródło
Odpowiedzi:
Żaden język nie jest idealny do wszystkich zadań, a Objective-C nie jest wyjątkiem, ale są pewne bardzo specyficzne subtelności. Podobnie jak w przypadku używania
LINQ
ivar
(dla których nie jestem świadomy bezpośredniego zastąpienia), niektóre z nich są ściśle związane z językiem, a inne są związane z frameworkiem.( UWAGA: Tak jak C # jest ściśle powiązany z .NET, Objective-C jest ściśle powiązany z Cocoa. Dlatego niektóre z moich punktów mogą wydawać się niezwiązane z Objective-C, ale Objective-C bez Cocoa jest podobne do C # bez .NET / WPF / LINQ, działające w trybie Mono itp. To po prostu nie jest sposób, w jaki zwykle się to robi).
Nie będę udawać, że w pełni omawiam różnice, zalety i wady, ale oto kilka, które przychodzą mi do głowy.
Jedną z najlepszych części Objective-C jest dynamiczna natura - zamiast wywoływać metody, wysyłasz komunikaty, które środowisko wykonawcze kieruje dynamicznie. W połączeniu (rozsądnie) z dynamicznym pisaniem, może to uczynić wiele potężnych wzorców prostszymi lub nawet trywialnymi do wdrożenia.
Jako ścisły nadzbiór C, Objective-C ufa, że wiesz, co robisz. W przeciwieństwie do podejścia zarządzanego i / lub bezpiecznego dla typów języków, takich jak C # i Java, Objective-C pozwala robić, co chcesz i doświadczać konsekwencji. Oczywiście czasami może to być niebezpieczne, ale fakt, że język nie przeszkadza aktywnie w robieniu większości rzeczy, jest dość potężny. ( EDIT: należy wyjaśnić, że C # posiada również „niebezpiecznych” cechy i funkcje, ale domyślne zachowanie jest zarządzany kod, który trzeba jawnie zrezygnować z porównania Java. Tylko pozwala na typesafe kodu i nie naraża surowych wskaźników w tak jak C i inni).
Kategorie (dodawanie / modyfikowanie metod w klasie bez podklas lub dostępu do źródła) to niesamowity miecz obosieczny. Może znacznie uprościć hierarchie dziedziczenia i wyeliminować kod, ale jeśli zrobisz coś dziwnego, wyniki mogą czasami być zaskakujące.
Cocoa sprawia, że tworzenie aplikacji GUI jest o wiele prostsze na wiele sposobów, ale musisz ogarnąć ten paradygmat. Projekt MVC jest wszechobecny w kakao, a wzorce, takie jak delegaci, powiadomienia i wielowątkowe aplikacje GUI, są dobrze dopasowane do Objective-C.
Wiązania Cocoa i obserwacja klucz-wartość mogą wyeliminować mnóstwo kodu kleju, a struktury Cocoa w dużym stopniu to wykorzystują. Dynamiczne wysyłanie Objective-C działa ręka w rękę z tym, więc typ obiektu nie ma znaczenia, o ile jest zgodny z kluczem-wartością.
Prawdopodobnie przegapisz typy generyczne i przestrzenie nazw, i mają one swoje zalety, ale w podejściu i paradygmacie Objective-C byłyby bardziej subtelne niż konieczne. (Generics dotyczy bezpieczeństwa typów i unikania rzutowania, ale dynamiczne pisanie w Objective-C sprawia, że zasadniczo nie stanowi to problemu. Przestrzenie nazw byłyby fajne, gdyby były dobrze wykonane, ale jest wystarczająco proste, aby uniknąć konfliktów, których koszt prawdopodobnie przewyższa korzyści, zwłaszcza dla starszego kodu).
W przypadku współbieżności bardzo przydatne są bloki (nowa funkcja językowa w Snow Leopard, zaimplementowana w dziesiątkach interfejsów API Cocoa). Kilka wierszy (często w połączeniu z Grand Central Dispatch, który jest częścią libsystem w wersji 10.6) może wyeliminować znaczący schemat funkcji wywołania zwrotnego, kontekstu itp. (Bloki mogą być również używane w C i C ++ i na pewno można je dodać do C #, co byłoby niesamowite.) NSOperationQueue jest również bardzo wygodnym sposobem dodawania współbieżności do własnego kodu, wysyłając niestandardowe podklasy NSOperation lub anonimowe bloki, które GCD automatycznie wykonuje w jednym lub kilku różnych wątkach.
źródło
alloca
. Po prostu nie czyni ich tak łatwo dostępnymi - musisz wyraźnie wyrazić zgodę.Programuję w C, C ++ i C # już od ponad 20 lat, po raz pierwszy zacząłem w 1990 roku. Właśnie postanowiłem rzucić okiem na rozwój iPhone'a oraz Xcode i Objective-C. O mój Boże ... wszystkie skargi na Microsoft, które cofam, teraz zdaję sobie sprawę, jak zły był kod. Cel-C jest zbyt złożony w porównaniu z tym, co robi C #. Byłem zepsuty językiem C # i teraz doceniam całą ciężką pracę włożoną przez Microsoft. Samo odczytanie Objective-C z wywołaniami metod jest trudne do odczytania. C # jest w tym elegancki. To tylko moja opinia, miałem nadzieję, że język programowania Apple był tak dobry, jak produkty Apple, ale droga mi, muszą się wiele nauczyć od Microsoftu. Nie ma wątpliwości, aplikacja w C # .NET Mogę uruchomić aplikację wielokrotnie szybciej niż XCode Objective-C. Apple z pewnością powinno wyciągnąć kartkę z książki Microsoftu, a wtedy mielibyśmy idealne środowisko. :-)
źródło
"Just reading Objective-C with method invokes is difficult to read"
- oto tylko jeden bardzo subiektywny argument, który został tutaj wymieniony jako wady Obj-C. Wszystko inne to tylko dyskusyjna retoryka.Nie ma tu przeglądu technicznego, ale po prostu uważam, że Objective-C jest znacznie mniej czytelny. Biorąc pod uwagę przykład, który dał ci Cinder6:
DO#
List<string> strings = new List<string>(); strings.Add("xyzzy"); // takes only strings strings.Add(15); // compiler error string x = strings[0]; // guaranteed to be a string strings.RemoveAt(0); // or non-existant (yielding an exception)
Cel C
NSMutableArray *strings = [NSMutableArray array]; [strings addObject:@"xyzzy"]; [strings addObject:@15]; NSString *x = strings[0]; [strings removeObjectAtIndex:0];
Wygląda okropnie. Próbowałem nawet przeczytać 2 książki na ten temat, zgubili mnie wcześnie i zwykle nie rozumiem tego z książkami / językami programowania.
Cieszę się, że mamy Mono dla Mac OS, ponieważ gdybym musiał polegać na Apple, aby zapewnić mi dobre środowisko programistyczne ...
źródło
[NSMutableArray array]
zamiast tego (przecieka pamięć), a czwarta linia powinna zaczynać się odNSString* x
orid x
(błąd kompilacji) ... Tak, w Objective-C brakuje typów generycznych (szczerze nie brakuje mi ich), nie 't indeksuje obiekty ze składnią tablicową, a interfejsy API są generalnie bardziej szczegółowe. To-may-to, to-mah-to. To naprawdę sprowadza się do tego, co wolisz zobaczyć. (Możesz napisać ten sam kod w C ++ STL i pomyślałem, że byłby ohydny). Dla mnie czytelny kod często oznacza, że tekst kodu mówi ci, co robi, a zatem kod Objective-C jest preferowany.List<T>.Remove
przyjmuje ciąg jako argument i usuwa pierwsze wystąpienie tego ciągu. Aby usunąć według indeksu, potrzebujeszRemoveAt
.removeObjectAtIndex:
, choć bardziej szczegółowa, jest również jednoznaczna co do tego, co robi.strings[0]
istrings.RemoveAt(0)
zmniejsza jasność, przynajmniej dla mnie. (Poza tym zawsze denerwuje mnie, gdy nazwy metod zaczynają się wielką literą ... Wiem, że to drobny drobiazg, ale to po prostu dziwne.)Ręczne zarządzanie pamięcią jest czymś, z czym początkujący, dla Objective-C, mają najwięcej problemów, głównie dlatego, że uważają, że jest to bardziej złożone niż jest.
Cel C i kakao w rozszerzeniu opierają się na konwencjach dotyczących egzekwowania; znasz i przestrzegasz bardzo małego zestawu reguł, a dzięki dynamicznemu środowisku wykonawczemu dostajesz dużo za darmo.
Nie w 100% prawdziwa zasada, ale wystarczająco dobra na co dzień to:
alloc
powinno być połączone z arelease
na końcu bieżącego zakresu.alloc
, powinna zostać zwrócona przezreturn [value autorelease];
zamiast dopasowywania przezrelease
.Dalej następuje dłuższe wyjaśnienie.
Zarządzanie pamięcią opiera się na własności; tylko właściciel instancji obiektu powinien kiedykolwiek zwolnić obiekt, wszyscy inni powinni zawsze nic nie robić. Oznacza to, że w 95% całego kodu traktujesz Objective-C tak, jakby był wyrzucany jako śmieci.
A co z pozostałymi 5%? Masz trzy metody, na które należy zwrócić uwagę, każda instancja obiektu otrzymana z tych metod jest własnością bieżącego zakresu metody :
alloc
new
lubnewService
.copy
imutableCopy
.Metoda ma trzy możliwe opcje dotyczące tego, co zrobić z instancjami należącymi do jej obiektów przed zakończeniem działania:
release
jeśli nie jest już potrzebny.autorelease
.Kiedy więc powinieneś aktywnie przejąć własność dzwoniąc
retain
? Dwie sprawy:źródło
Jasne, jeśli wszystko, co widziałeś w swoim życiu, jest celem C, to jego składnia wygląda na jedyną możliwą. Moglibyśmy nazwać cię „dziewicą programowania”.
Ale ponieważ dużo kodu jest napisanych w C, C ++, Java, JavaScript, Pascal i innych językach, zobaczysz, że ObjectiveC różni się od nich wszystkich, ale nie w dobry sposób. Czy mieli ku temu powód? Zobaczmy inne popularne języki:
C ++ dodał wiele dodatków do C, ale zmienił oryginalną składnię tylko w razie potrzeby.
C # dodał wiele dodatków w porównaniu do C ++, ale zmienił tylko rzeczy, które były brzydkie w C ++ (jak usunięcie „::” z interfejsu).
Java zmieniła wiele rzeczy, ale zachowała znajomą składnię z wyjątkiem części, w których zmiana była potrzebna.
JavaScript jest całkowicie dynamicznym językiem, który może zrobić wiele rzeczy, których ObjectiveC nie może. Jednak jego twórcy nie wymyślili nowego sposobu wywoływania metod i przekazywania parametrów tylko po to, by różniły się od reszty świata.
Visual Basic może przekazywać parametry poza kolejnością, podobnie jak ObjectiveC. Możesz nazwać parametry, ale możesz też przekazać je w zwykły sposób. Cokolwiek używasz, jest to normalny sposób rozdzielania przecinkami, który wszyscy rozumieją. Przecinek jest zwykłym ogranicznikiem, nie tylko w językach programowania, ale w książkach, gazetach i ogólnie w języku pisanym.
Object Pascal ma inną składnię niż C, ale jego składnia jest w rzeczywistości ŁATWIEJSZA dla programisty (może nie dla komputera, ale kogo to obchodzi, co myśli komputer). Może więc odeszli, ale przynajmniej ich wynik jest lepszy.
Python ma inną składnię, która jest jeszcze łatwiejsza do odczytania (dla ludzi) niż Pascal. Więc kiedy go zmienili, zmieniając, przynajmniej uczynili to lepszym dla nas, programistów.
A potem mamy ObjectiveC. Dodanie pewnych ulepszeń do C, ale wymyślenie własnej składni interfejsu, wywoływanie metod, przekazywanie parametrów i co nie. Zastanawiam się, dlaczego nie zamienili + i - tak, że plus odejmuje dwie liczby. Byłoby jeszcze fajniej.
Steve Jobs spieprzył, wspierając ObjectiveC. Oczywiście nie obsługuje C #, co jest lepsze, ale należy do jego najgorszego konkurenta. Jest to więc decyzja polityczna, a nie praktyczna. Technologia zawsze cierpi, gdy decyzje techniczne są podejmowane z powodów politycznych. Powinien kierować firmą, którą robi dobrze, a sprawy programistyczne pozostawić prawdziwym ekspertom.
Jestem pewien, że byłoby jeszcze więcej aplikacji na iPhone'a, gdyby zdecydował się napisać iOS i obsługiwać biblioteki w jakimkolwiek innym języku niż ObjectiveC. Dla wszystkich oprócz zagorzałych fanów, dziewiczych programistów i Steve'a Jobsa, ObjectiveC wygląda śmiesznie, brzydko i odrażająco.
źródło
NSArray
i obsługuje on wybór najlepszego algorytmu na podstawie maszyny i natury danych.Jedną z rzeczy, które uwielbiam w Objective-c, jest to, że system obiektowy jest oparty na komunikatach, pozwala robić naprawdę fajne rzeczy, których nie można było zrobić w C # (przynajmniej nie dopóki nie obsługują dynamicznego słowa kluczowego!).
Kolejną świetną rzeczą w pisaniu aplikacji cocoa jest Interface Builder, jest o wiele ładniejszy niż projektant formularzy w Visual Studio.
Rzeczy związane z obj-c, które mnie denerwują (jako programistę C #) to fakt, że musisz zarządzać własną pamięcią (jest zbieranie śmieci, ale to nie działa na iPhonie) i może być bardzo rozwlekłe z powodu składnia selektora i wszystkie [].
źródło
dynamic
dostaniesz tylko w połowie - implementacja prawdziwego dynamicznego obiektu, nawet w przypadku błahych rzeczy, takich jak delegowanie wiadomości, jest żmudna nawet w C # 4.0. Z drugiej strony ceną za elastyczność prawdziwie dynamicznego przekazu przekazującego a la ObjC jest utrata bezpieczeństwa typu.System.Reflection
połączeniu z rozszerzeniami w C # 3.0, możesz wywołać dowolną metodę, którą znajdziesz, ale nie jest to prawdziwe przekazywanie wiadomości, będzie wyglądać tak,obj.PassMessage("function_name", params object[] args);
aby lepsze przekazywanie wiadomości było zintegrowane z językiem, brak metody wywoływanej na normalnym obiekcie byłoby potrzebne.Jako programista dopiero zaczynający pracę z Objective-C na iPhone'a, pochodzący z C # 4.0, brakuje mi wyrażeń lambda, a zwłaszcza Linq-to-XML. Wyrażenia lambda są specyficzne dla C #, podczas gdy Linq-to-XML jest w rzeczywistości bardziej kontrastem .NET vs. Cocoa. W przykładowej aplikacji, którą pisałem, miałem trochę XML w ciągu. Chciałem przeanalizować elementy tego XML-a w kolekcję obiektów.
Aby to osiągnąć w Objective-C / Cocoa, musiałem użyć klasy NSXmlParser . Ta klasa opiera się na innym obiekcie, który implementuje protokół NSXMLParserDelegate z metodami, które są wywoływane (odczyt: wysłane wiadomości), gdy czytany jest otwarty tag elementu, gdy czytane są dane (zwykle wewnątrz elementu) i gdy czytany jest znacznik końcowy elementu . Musisz śledzić stan i stan analizowania. I szczerze mówiąc, nie mam pojęcia, co się stanie, jeśli XML jest nieprawidłowy. Świetnie nadaje się do zagłębiania się w szczegóły i optymalizacji wydajności, ale o rany, to cała masa kodu.
W przeciwieństwie do tego, oto kod w C #:
using System.Linq.Xml; XDocument doc = XDocument.Load(xmlString); IEnumerable<MyCustomObject> objects = doc.Descendants().Select( d => new MyCustomObject{ Name = d.Value});
I to wszystko, masz kolekcję niestandardowych obiektów narysowanych z XML. Jeśli chcesz odfiltrować te elementy według wartości, lub tylko do tych, które zawierają określony atrybut, lub jeśli chcesz tylko pierwszych 5, lub jeśli chcesz pominąć pierwszy 1 i uzyskać następne 3, lub po prostu dowiedzieć się, czy jakiekolwiek elementy zostały zwrócone ... BAM, wszystko w tym samym wierszu kodu.
Istnieje wiele klas open-source, które znacznie ułatwiają to przetwarzanie w Objective-C, więc to robi większość ciężkiego podnoszenia. Po prostu nie jest to wbudowane.
* UWAGA: W rzeczywistości nie skompilowałem powyższego kodu, ma on służyć jako przykład ilustrujący względny brak szczegółowości wymaganej przez C #.
źródło
Prawdopodobnie najważniejszą różnicą jest zarządzanie pamięcią. Dzięki C # uzyskujesz wyrzucanie elementów bezużytecznych, ponieważ jest to język oparty na CLR. Z Objective-C musisz samodzielnie zarządzać pamięcią.
Jeśli wywodzisz się z języka C # (lub dowolnego współczesnego języka), przejście na język bez automatycznego zarządzania pamięcią będzie naprawdę bolesne, ponieważ spędzisz dużo czasu na kodowaniu na odpowiednim zarządzaniu pamięcią (i debugowaniu jako dobrze).
źródło
Oto całkiem dobry artykuł porównujący te dwa języki: http://www.coderetard.com/2008/03/16/c-vs-objective-c/
źródło
Poza różnicą paradygmatu między dwoma językami, nie ma dużej różnicy. Chociaż nie chcę tego mówić, możesz robić te same rzeczy (prawdopodobnie nie tak łatwo) z .NET i C #, jak z Objective-C i Cocoa. Począwszy od Leoparda, Objective-C 2.0 ma funkcję zbierania śmieci, więc nie musisz samodzielnie zarządzać pamięcią, chyba że chcesz (zgodność kodu ze starszymi aplikacjami na komputery Mac i iPhone to 2 powody, aby chcieć).
Jeśli chodzi o uporządkowany, czytelny kod, znaczna część jego obciążenia spoczywa na programistach, tak jak w przypadku każdego innego języka. Jednak uważam, że paradygmat przekazywania wiadomości dobrze nadaje się do czytelnego kodu, pod warunkiem, że odpowiednio nazwiesz swoje funkcje / metody (ponownie, tak jak każdy inny język).
Jako pierwszy przyznam, że niezbyt dobrze znam C # czy .NET. Ale powody, dla których Quinn wymieniony powyżej, to kilka powodów, dla których nie chcę się takim stać.
źródło
Wywołania metody użyte w obj-c make do łatwego odczytu kodu, moim zdaniem o wiele bardziej eleganckie niż c # i obj-c jest zbudowane na podstawie c, więc cały kod c powinien działać dobrze w obj-c. Największym sprzedawcą jest jednak to, że obj-c to otwarty standard, więc możesz znaleźć kompilatory dla dowolnego systemu.
źródło