Java анонимный класс как служебные функции? Для разработки Аргументов, которые на самом деле используются, или один Аргумент (больший объект)
Ситуация такова, что мне нужно использовать указатели функций для очень многих функций в Java (поэтому я сделал это таким образом) и сохранить каждый анонимный класс в статическую переменную интерфейса, чтобы я мог использовать их напрямую.
/** The Constant HARDLIM. */
public static final TransferePatternable HARDLIM =
new TransferePatternable() {
public DoubleMatrix transfere(DoubleMatrix netSum, double theta) {
return netSum.gt(theta);
}
public String getFuncName() {
return "HARDLIM";
}
};
Но проблема в том, что иногда мне не нужно предоставлять Theta, поэтому, если я удаляю его, полиморфизм не будет работать, (2 функции из 10 не нуждаются в theta), поэтому я должен был поставить его (соглашения об объявлении функций сейчас Ужасно) поэтому я подумал о том, чтобы передать весь Объект, который на самом деле содержит как netsum, так и theta.
Но я начинаю беспокоиться, потому что это также разрушит то, для чего эта функция действительно предназначена. Наконец, я предложил поместить эти функции отдельно (не анонимно), а затем заставить их использовать анонимные функции, но аргумент был бы объектом. Как следующее:
/** The Constant HARDLIM. */
public static final TransferePatternable HARDLIM =
new TransferePatternable() {
public DoubleMatrix transfere(MyObject obj) {
return MyObjectUtilFun.hardlim(obj.getNetsum,obj.getTheta);
}
public String getFuncName() {
return "HARDLIM";
}
};
Так я делаю правильные шаги? или я бездельничаю, пожалуйста, ведите меня!
4 ответа
В конце я использовал второй вариант, но с некоторыми замечаниями:
- Всегда иметь функции (т.е. Hardlim), определенные независимо в служебных классах.
- Чтобы указать в Javadocs, что это за переменная на самом деле и какая функция полезности используется.
Я также обнаружил, что цена путаницы в пользователях с ненужными аргументами высока, потому что приложение уже сложное, нет необходимости усложнять.
public static final TransferePatternable HARDLIM = new TransferePatternable() { public DoubleMatrix transfere(MyObject obj) { return MyObjectUtilFun.hardlim(obj.getNetsum,obj.getTheta); } public String getFuncName() { return "HARDLIM"; } };
Вам действительно нужен экземпляр, чтобы быть public static final
? Если вы можете создать экземпляр экземпляра везде, где у вас есть ссылка на тета, тогда ваш анонимный класс может использовать эту тета-ссылку. Например:
final double theta = 123d;
class TransferePatternable {
public String transfere(String whatever) {
return whatever + theta;
}
}
TransferePatternable myInstance = new TransferePatternable();
myInstance.transfere("arg");
В качестве альтернативы вы можете указать входные данные как общий тип, так что ваш MyObject
не обязательно должен быть надмножеством всех возможных входов, а может отличаться в зависимости от типа TransferePatternable. Очевидно, что недостатком здесь является то, что вам нужно знать, какой тип вы вызываете, чтобы обеспечить правильный ввод, но вам все равно нужно это знать, если вы не хотите предоставлять тэту в некоторых ситуациях.
Наконец, еще одно распространенное решение этой проблемы - заменить ВСЕ параметры метода только одним Map
, Затем вы можете передать все, что вы хотите! У этого есть много очевидных недостатков, но многие API делают именно это, и обычно вы увидите, что они называют карту "контекстом". Вот несколько примеров:
javax.servlet .ServletRequest
сохранить параметры вMap
- АОП имеет
javax.interceptor.InvocationContext
учебный класс - Контейнер Spring IoC в основном большой
Map
из названных javabeans - Язык выражений JSP позволяет ссылаться на неявные объекты, которые в основном хранятся в нескольких
Map
s
Я сам использовал это Map
решение при реализации Excel-подобный язык формул в Java лет назад. Такая формула может быть разбита на функции и переменные, и при выполнении функции мы предоставили Map
содержит переменные с ключом по имени переменной. Очевидно, вам все еще нужно знать кое-что о том, что вы вызываете, и на самом деле мы всегда знали достаточно о формуле, которая обеспечивает правильные входные данные в Map
было легко. Но опять же я должен предупредить вас: этот вид кода довольно сложно реализовать и поддерживать. Если вы не планируете наращивать большой набор функций с течением времени, не идите по этому пути. Это не OO-friendly, и это должно быть последним средством.
Если MyObject
это обычно используемый интерфейс или класс и TransferePatternable
не ожидается работы с чем-то еще, ваша вторая идея лучше. Это открывает возможности TransferePatternable, способного работать не только с netSum и тэтой, и избавляет от ненужной тэты. Я предполагаю, что это то, что вы хотите сделать, даже если это означает расширение возможностей, объема и важности класса / интерфейса MyObject.
Но вы ограничиваете TransferePatternable для работы с экземпляром MyObject. Неиспользованная тэта - проблема, но это небольшая цена, чтобы заплатить за силу полиморфизма (и это намного проще и аккуратнее, чем большинство других решений). Если решение MyObject не выглядит для вас идеальным, придерживайтесь неиспользованной тэты. Я думаю, хорошая идея придет рано или поздно, без вреда, если это не так.
Есть ли какая-то причина, по которой у вас не может быть перегруженной функции "передачи" в HARDLIM?
/** The Constant HARDLIM. */
public static final TransferePatternable HARDLIM =
new TransferePatternable() {
public DoubleMatrix transfere(DoubleMatrix netSum, double theta) {
return netSum.gt(theta);
}
public DoubleMatrix transfere(DoubleMatrix netSum) {
return netSum.whateverYouNeedToDoWithoutTheta();
}
public String getFuncName() {
return "HARDLIM";
}
};