Znam Javę, a teraz uczę się Objective-C. Jakie dokładnie są różnice między interfejsami Java a protokołami Objective-C?
źródło
Znam Javę, a teraz uczę się Objective-C. Jakie dokładnie są różnice między interfejsami Java a protokołami Objective-C?
Na początek trochę historycznego spojrzenia na temat od jednego z twórców Javy. Następnie Wikipedia ma średnio przydatną sekcję dotyczącą protokołów Objective-C . W szczególności zrozum, że Objective-C obsługuje zarówno formalne protokoły (które są wyraźnie zadeklarowane za pomocą @protocol
słowa kluczowego, odpowiednik interfejsu Java), jak i nieformalne protokoły (tylko jedna lub więcej metod implementowanych przez klasę, które można wykryć poprzez odbicie).
Jeśli zastosujesz formalny protokół (terminologia Objective-C dla „implementacji interfejsu”), kompilator wyemituje ostrzeżenia o niezaimplementowanych metodach, tak jak można się tego spodziewać w Javie. W przeciwieństwie do Javy (jak wspomniał skaffman ), jeśli klasa Objective-C implementuje metody zawarte w formalnym protokole, mówi się, że „jest zgodna” z tym protokołem, nawet jeśli jej interfejs wyraźnie go nie przyjmuje.Możesz przetestować zgodność protokołu w kodzie (używając -conformsToProtocol:) w następujący sposób:
if ([myObject conformsToProtocol:@protocol(MyProtocol)]) {
...
}
UWAGA: Dokumentacja Apple stwierdza:
„Ta metoda określa zgodność wyłącznie na podstawie formalnych deklaracji w plikach nagłówkowych, jak pokazano powyżej. Nie sprawdza, czy metody zadeklarowane w protokole są rzeczywiście zaimplementowane - za to odpowiada programista”.
Od wersji Objective-C 2.0 (w OS X 10.5 „Leopard” i iOS) formalne protokoły mogą teraz definiować metody opcjonalne , a klasa jest zgodna z protokołem, o ile implementuje wszystkie wymagane metody. Możesz użyć słów kluczowych @required
(domyślnych) i, @optional
aby przełączyć, czy deklaracje metod, które następują, muszą lub mogą być zaimplementowane w celu zgodności z protokołem. (Zobacz sekcję podręcznika języka programowania Objective-C 2.0 firmy Apple, w którym omówiono opcjonalne metody protokołów ).
Opcjonalne metody protokołów zapewniają programistom dużą elastyczność, szczególnie w zakresie implementowania delegatów i słuchaczy . Zamiast rozszerzać coś w rodzaju MouseInputAdapter (co może być denerwujące, ponieważ Java jest również dziedziczeniem pojedynczym) lub implementować wiele bezcelowych, pustych metod, możesz przyjąć protokół i zaimplementować tylko te opcjonalne metody, na których Ci zależy. W przypadku tego wzorca obiekt wywołujący sprawdza, czy metoda jest zaimplementowana przed jej wywołaniem (przy użyciu -respondsToSelector ), tak jak poniżej :
if ([myObject respondsToSelector:@selector(fillArray:withObject:)]) {
[myObject fillArray:anArray withObject:foo];
...
}
Jeśli narzut odbicia stanie się problemem, zawsze możesz buforować wynik boolowski w celu ponownego wykorzystania , ale powstrzymaj się przed przedwczesną optymalizacją. :-)
-conformsToProtocol:
zwróci TAK tylko wtedy, gdy klasa jawnie przyjmie protokół. Czy nawet tego próbowałeś?-conformsToProtocol:
rzeczywiście wymaga, aby klasa (lub przodek) formalnie zadeklarowała, że przyjmuje protokół. Nie wiem, jak to źle zrozumiałem, dzięki za korektę!Są prawie identyczne. Jednak jedyną rzeczą, która mnie złapała, jest to, że jeśli wyraźnie nie zadeklarujesz, że obiektywny protokół C również implementuje NSObject, odniesienia do tego protokołu nie uzyskują dostępu do metod deklarowanych przez NSObject (i tak bez ostrzeżenia kompilatora). Dzięki java możesz mieć odniesienie do interfejsu i nadal wywoływać na nim toString () itp.
na przykład
Cel C:
@protocol MyProtocol // Protocol definition @end id <MyProtocol> myProtocol; [myProtocol retain] // Compiler warning
Jawa:
public interface MyInterface { // interface definition } MyInterface myInterface; myInterface.toString(); // Works fine.
Cel C (naprawiony):
@protocol MyProtocol <NSObject> // Protocol definition @end id <MyProtocol> myProtocol; [myProtocol retain] // No Warning
źródło