Может ли Java сделать что-то вроде категории в Objective C?
Рассмотрим следующую ситуацию:
Object > MyClass > MyClassA, MyClassB
Если я хочу что-то на уровне объекта, например, я добавил printDetail(); Как я могу это сделать в реализации Java? Более того, я могу переопределить весь метод Object. Например, мне нужно иметь совершенно новый .toString(), могу ли я переопределить его? Спасибо.
Ответы
Ответ 1
Нет, это не так, на самом деле. Objective C - это динамически типизированный и ограниченный язык, что делает его очень доступным для таких функций, как категории. Ближе всего вы можете прийти к этому в Java - это инструментарий класса с помощью библиотеки манипулирования байтом, например ASM или Javassist.
Но на самом деле, при использовании строго типизированного языка OO, такого как Java, вы должны использовать его функции, а не пытаться дублировать их на другом языке.
Ответ 2
Как уже упоминалось в других ответах, нет ничего действительно подобного категории. У меня есть некоторые общие решения, которые я использую для некоторых категорий в моем коде objective-c при переносе на java. Многие из моих категорий objective-c существуют, потому что я не хочу расширять базовые классы iOS, но я хочу добавить некоторые функции к этому классу. Многие из этих категорий objective-c не добавляют свойства, используя objc_SetAssociatedObject. В тех случаях я использую статический вспомогательный класс в Java. Рассмотрим пример с использованием NSString и String. Я добавлю функциональность для добавления цитат в строку. Мы предположим, что это полезно и не существует для целей иллюстрации. В objective-c мы могли бы:
@interface NSString (MyCategory)
/**
* Creates and autoreleased image from self.
*/
- (NSString*)quotedString;
@end
@implementation NSString (MyCategory)
- (NSString *)quotedString
{
return [NSString stringWithFormat:@"\"%@\"", self];
}
@end
Вы бы назвали это откуда-то вроде этого:
NSString *myString = @"When you're curious, you find lots of interesting things to do.";
NSString *quotedString = [myString quotedString];
Вот как я мог бы реализовать это в Java:
public class StringHelper {
public static String quotedString(String that) {
return '"' + that + '"';
}
}
И чтобы называть его:
String myString = = "When you're curious, you find lots of interesting things to do.";
String quotedString = StringHelper.quotedString(myString);
Если вы думаете о методах категорий как методах, которые автоматически отправляют переменную self как первый аргумент метода (хотя и невидимый), тогда это имеет еще больший смысл.
В вашем примере, если бы я не расширил конкретный объект, я мог бы сделать что-то вроде:
public class ObjectHelper {
public static void printDetail(Object that) {
// do what it takes;
}
}
ОБНОВЛЕНИЕ: комментатор попросил ограничения.
Ограничения состоят в том, что код находится в отдельном статическом классе. Это не так удобно, как категория. Вы должны помнить эти имена классов или находить их, и вы не получите автоматическое завершение по своим исходным методам объектов в помощнике. Кроме того, вы не можете использовать свойства или атрибуты уровня объекта, которые вы получаете с objc_SetAssociatedObject. Вы можете использовать хэш-карту и создать нечто похожее с исходным экземпляром объекта как хэш-ключ.
public class StringHelper {
private static Map<String, Integer> order = new HashMap();
public static int getOrder(String that) {
if(that == null) { return 0; }
Integer ret = StringHelper.order.get(that);
if(ret == null) { return 0; }
else { return ret; }
}
public static void setOrder(String that, int order) {
if(that != null) {
StringHelper.order.put(that, order);
}
}
}
Также нет именных столкновений с исходным классом, что было бы более полезным. Названия имен в категориях objective-c считаются плохими.
Ответ 3
Все классы Java в конечном итоге имеют java.lang.Object
. Из-за этого все методы Java classes inherit
из Object
. Половина этих методов final
и не может быть overridden
. Однако другие методы в объекте могут быть и переопределены
Метод toString() в классе Object используется для отображения некоторой информации о любом объекте.
Таким образом, вы можете переопределить его в соответствии с вашим...
EX..
public class Test{
@Override
public String toString() {
/// staff
}
}