Ответственность за загрузку файлов класса несет ClassLoader. Давайте посмотрим, что произойдет, когда мы напишем наши собственные классы.
Пример 1:
class StaticTest {
static int a;
int b;
int c;
}
Теперь мы можем видеть, что класс «StaticTest» имеет 3 поля. Но на самом деле нет существования переменной b, c. Но почему ???. Ладно, посмотрим. Здесь b, c - переменная экземпляра. Поскольку переменная экземпляра получает память во время создания объекта. Итак, здесь b, c пока не получают никакой памяти. Вот почему не существует b, c. Итак, существует только существование a. Для ClassLoader у него есть только одна информация о. ClassLoader еще не распознает b, c, потому что объект еще не создан.
Давайте посмотрим другой пример: Пример 2:
class StaticTest {
public void display() {
System.out.println("Static Test");
}
public static void main(String []cmd) {
display();
}
}
Теперь, если мы попытаемся скомпилировать этот код, компилятор даст Ошибка CE. CE: отображение нестатического метода () не может ссылаться на статический контекст.
Теперь для ClassLoader это выглядит так:
class StaticTest {
public static void main(String []cmd) {
display();
}
}
В примере 2 Ошибка CE - это потому, что мы вызываем нестационарный метод из статического контекста. Таким образом, ClassLoader не может распознавать метод display () во время компиляции. Так возникает ошибка компиляции.
Если вам нужен хакерский способ сделать это, что включает в себя выключение с целью выполнения-c, вы всегда можете использовать метод swizzling (вставьте здесь стандартные отказы). Это позволит вам хранить разные методы как арбитраж назвал селекторов, а затем поменяйте их во время выполнения, сколько вам нужно.
С помощью swizzling «helper» методов, включенных в ConciseKit , вы фактически вызываете реализацию по умолчанию ... достаточно странно .. путем вызова вашей реализации SWIZZLED ..
Вы установили его в + (void) load
, вызвав + (BOOL)swizzleMethod:(SEL)originalSelector with:(SEL)anotherSelector in:(Class)klass;
, то есть
[$ swizzleMethod:@selector(oldTired:)
with:@selector(swizzledHotness:) in:self.class];
, а затем в swizzled method .. давайте предположим, что он возвращает -(id)
.. вы можете сделать свое зло , или по какой-либо причине вы в первую очередь задираете ... а затем вместо возвращения объекта или self
или еще чего ...
return [self swizzledHotness:yourSwizzledMethodsArgument];
В этом методе похоже, что мы снова вызываем тот же метод, вызываем и бесконечную рекурсию. Но к тому времени, когда эта линия будет достигнута, оба метода были заменены. Поэтому, когда мы вызываем swizzled_synchronize, мы на самом деле вызываем оригинальный метод.
blockquote>Он чувствует и выглядит странно, но .. он работает. Это позволяет добавлять бесконечные приукрашивания к существующим методам и по-прежнему «называть супер» (фактически «я») и использовать преимущества ручной работы оригинального метода ... даже без доступа к исходному источнику.
Ознакомьтесь с моей статьей о решении, найденном в библиотеке разработчиков Mac: http://codeshaker.blogspot.com/2012/01/calling-original-overridden-method-from.html
В принципе, это то же самое, что и описанный выше метод Swizzling с кратким примером:
#import <objc/runtime.h> @implementation Test (Logging) - (NSUInteger)logLength { NSUInteger length = [self logLength]; NSLog(@"Logging: %d", length); return length; } + (void)load { method_exchangeImplementations(class_getInstanceMethod(self, @selector(length)), class_getInstanceMethod(self, @selector(logLength))); } @end
Из comp.lang.objective-C FAQ listing : «Что, если несколько категорий реализуют один и тот же метод? Тогда ткань Вселенной, как мы ее знаем, перестает существовать. Собственно, это не совсем true, но, безусловно, будут возникать некоторые проблемы. Когда категория реализует метод, который уже появился в классе (будь то через другую категорию или в качестве первичного @implementation класса), определение этой категории перезаписывает ранее существующее определение. Обратите внимание, что если две категории переписывают один и тот же метод, то в зависимости от того, что было загружено последними «выигрышами», которые невозможно предсказать до запуска кода. »
Из developer.apple.com : «Когда категория переопределяет унаследованный метод, метод в категории может, как обычно, вызывать унаследованную реализацию через сообщение супер. Однако, если категория переопределяет метод, который уже существовал в классе категории, re не может ссылаться на исходную реализацию "
super
должен решить исходный объект. В конце концов, категория очень похожа на подкласс (например, вы можете переопределить методы).
– Raffi Khatchadourian
2 February 2012 в 11:14
super
не будет разрешать «исходный объект».
– tooluser
9 May 2013 в 22:48