Chciałbym dziedziczyć z klasy szkieletowej, która ma metodę fabryczną. Jak mogę uczynić metodę factory zwrócić obiekt mojego odziedziczonego typu klasy? Znalazłem this useful article, które opisują podobną sytuację, ale w ich przypadku masz kontrolę nad nadklasą. Jak napisać, powiedzmy, podklasę UIImage
, która zwróci obiekt mojego podklasy?Dziedziczenie klasy C z metodami fabrycznymi
Odpowiedz
Chciałbym dziedziczyć z klasy szkieletowej, która ma metodę fabryki. Jak mogę uczynić metodę factory zwrócić obiekt mojego odziedziczonego typu klasy?
To wszystko co powinny zrobić:
@interface MONImage : UIImage
@end
@implementation MONImage
@end
Następnie:
MONImage * image = [MONImage imageNamed:name];
ImplementacjaJak mogę napisać, powiedzmy, podklasy UIImage że imageNamed: zwrócił obiekt typu mojej podklasy?
+[UIImage imageNamed:]
napisała podkategorizerów z tego podejścia. W związku z tym musisz sam wdrożyć tę metodę.
Oto jak jeden powinny zadeklarować metody fabryki:
+ (instancetype)imageNamed:(NSString *)pName;
i jak jeden powinny wdrożyć go:
+ (instancetype)imageNamed:(NSString *)pName
{
MONImage * image = [[self alloc] initWithThisDesignatedInitializer:pName];
^^^^ NOTE: self, not a concrete class
...set up image...
return image;
}
ale nie zrobili to w ten sposób - +[UIImage imageNamed:]
napisał podklasa i zwraca UIImage
podczas pisania MONImage * img = [MONImage imageNamed:pName];
. Czasami robi się to z dobrego powodu. Niektóre metody powinny mieć "ostateczną" semantykę. Często pojawia się, gdy twoja metoda może zwrócić wiele typów, tak jak w klastrze klasy. Język nie wyraża "ostatecznych" metod - ale taka metoda powinna być przynajmniej udokumentowana.
więc podjechać do tego UIImage
przypadku:
@interface MONImage : UIImage
+ (instancetype)imageNamed:(NSString *)pName;
@end
@implementation MONImage
+ (instancetype)imageNamed:(NSString *)pName
{
UIImage * source = [UIImage imageNamed:pName];
CGImageRef cgImage = source.CGImage;
if (cgImage)
return [[self alloc] initWithCGImage:cgImage];
// try it another way
return nil;
}
@end
Zauważ, że UIImage
s i CGImage
s są niezmienne. Nie powinno to skutkować głęboką kopią danych obrazu.
+1 za korzystanie z typu instancetype. – Abizern
czy to również zapewnia zachowanie buforowania '[UIImage imageNamed:]'? Jeśli nie, być może powinieneś zapisać odniesienie do oryginalnego obrazu w 'MONImage'. Ale naprawdę fajne rozwiązanie. –
@ JonathanCichon zachowałoby zachowanie wyszukiwania '+ imageNamed:'. ładowałby obraz, a następnie buforował go. dokładne zachowanie implementacji buforowania jest wyabstrahowane, więc mój wniosek jest taki, że nie gwarantuje się identyczności pod tym względem. Przypuszczam, że * to samo dotyczy buforowania, ale tego nie udowodniłem. dobre pytanie. – justin
Dla przykładu:
- Podklasa
UIImage
do, powiedzmy,MyImage
- Wdrożenie metody
imageNamed:
na nic konkretnego, które muszą być wykonane. - wywołanie tej metody w tej klasie:
MyImage *newImage = [MyImage imageNamed:imageName];
To naprawdę nie pomoże, ponieważ nie można nazwać 'super' we własnej implementacji' imageNamed', ponieważ spowoduje to zwrócenie instancji typu 'UIImage'. –
Kto powiedział, że musi zadzwonić super? może przydzielić i zainicjować obiekt swojej podklasy w metodzie i zwrócić to. I, jak wszyscy wiemy, konwencja jest dla podklas, aby wywoływać swój inicjator wyznaczonej superklasy, która zwraca obiekt typu "id". W każdym razie jest to wymyślny przykład oparty na tym, o co prosił OP. Szczegóły pozostawia się użytkownikowi, ale zasadą konstruktora wygody przydzielającego i inicjującego obiekt jego własnej klasy jest dźwięk. – Abizern
tak, ale w tym przypadku "magiczne" jabłko robi w "imageNamed:' jest bardzo użyteczne i nie sądzę, że chce to wdrożyć samodzielnie. Ale masz rację, twoja odpowiedź nie jest "zła", ale myślę, że nie jest bardzo przydatna w TEN przypadku. –
Podejście to rozwiązać mój problem był w użyciu kategorię zamiast dziedziczenia (kredyty przejść do Jonathan Cichon w komentarzach moje pytanie). Użyłem Associative References do zadeklarowania i przechowywania dodatkowych danych w implementacji kategorii, jak to omówiono tutaj w SO. Chciałbym zwrócić uwagę na zaproponowany przez Jonathana model NSObject
category implementation, który sprawia, że dodawanie odwołań asocjacyjnych do dowolnego obiektu jest naprawdę łatwe i eleganckie.
Podczas gdy cieszę się, że rozwiązałeś swój problem - twoje pytanie dotyczyło nadpisywania konstruktorów wygody, które następnie zmieniłeś na pytanie o dodanie pamięci do klasy poza rozszerzeniem klasy. Tak naprawdę są dwa zestawy pytań i odpowiedzi w tym samym czasie. – Abizern
Potrzebowałem rozszerzyć oryginalną klasę szkieletową o dodatkowe dane i nadal móc korzystać z jej oryginalnych konstruktorów wygody. Kiedy zadałem oryginalne pytanie, nie miałem pojęcia, jak to zrobić i przypuszczałem, że można to osiągnąć dzięki dziedziczeniu. Masz rację z punktu widzenia, że nie określiłem dokładnie, że muszę dodać dodatkowe dane do klasy, ale napisał "dziedziczenie". Z drugiej strony rozwiązanie Jonathana doskonale rozwiązuje mój problem, nawet jeśli nie korzystam z dziedziczenia. – MrTJ
UWAGA: Nie zmieniłem pierwotnego pytania i dodałem podpowiedź assoc.refs w tej odpowiedzi, tylko jako punkt odniesienia dla przyszłych czytelników. – MrTJ
- 1. Dziedziczenie z klasy szablonu w języku C++
- 2. C++ klasy i dziedziczenie szablonów
- 3. Klonowanie klasy C++ metodami czysto wirtualnymi
- 4. python: dziedziczenie klasy/dziedziczenie zmiennej z polimorfizmem?
- 5. Dziedziczenie z szablonu C++
- 6. dziedziczenie z podstawowej klasy konstruktora z parametrami
- 7. C# Interfejsy z opcjonalnymi metodami
- 8. C# Interfejs Dziedziczenie do klasy abstrakcyjnej
- 9. C# dziedziczenie
- 10. Dziedziczenie z nazwanej, pomniejszej klasy bazowej - Python
- 11. C++: Wiele dziedziczenie z polimorfizmem
- 12. C++: Czy dziedziczenie z klasy przenosi je do przestrzeni nazw?
- 13. C# Tworzenie instancji klasy rodzajowy które dziedziczenie z bazy
- 14. Dziedziczenie konstruktora z prywatnej klasy szablonów w C++
- 15. CSS - dziedziczenie klasy LESS
- 16. Wielokrotne dziedziczenie klasy niejednoznaczne baza
- 17. Dziedziczenie klasy jquery
- 18. klasy dziedziczenie typu Haskell
- 19. Uruchomić metodę przed wszystkimi metodami klasy
- 20. C++/CLI Dziedziczenie z natywnym C++ klasy z abstrakcyjnych metod i narażając go na C#
- 21. dziedziczenie szablonów C++
- 22. C# dziedziczenie bazy
- 23. Dziedziczenie przyjaźni w C++?
- 24. Dziedziczenie dziedziczenia w C#
- 25. Dziedziczenie klasy z argumentów konstruktora w java
- 26. .NET Dziedziczenie: stłumić właściwość z klasy bazowej
- 27. Interfejs Dziedziczenie w C++
- 28. C#: dziedziczenie konstruktorów
- 29. Wewnętrzne klasy Dziedziczenie w Kotlin
- 30. C# Dziedziczenie wielokrotne
może możesz osiągnąć to, co chcesz, pisząc kategorię na UIImage? –
Tak, teraz myślę o tym kierunku. Tyle tylko, że potrzebuję dodatkowych członków klasy (właściwości) i chciałem uniknąć kłopotów z objc_setAssociatedObject i przyjaciółmi. Również dlatego, że nie uważam za eleganckie stworzenie obejścia tego typu dla zupełnie innego problemu. Jednak obawiam się coraz bardziej, że nie mam wyboru. – MrTJ
spójrz na kategorię [NSObject] (https://github.com/pixelflut/PixLib-OpenSource/blob/master/PixLib%20OpenSource/NSObject%2BPixLib.m). Dwie metody "setRuntimeProperty: name:" i "runtimeProperty:" pomagają w ustawieniu i dostępie do powiązanych obiektów. –