#java #class #inheritance #multiple-inheritance
#java #класс #наследование #множественное наследование
Вопрос:
Я знаю, что этот вопрос задавался миллион раз, но я не могу найти достойного ответа.
У меня есть куча методов messenger, таких как debug(String)
и tell(CommandSender, String)
которые я хочу использовать для различных классов. Это звучит просто и легко, но отсутствие поддержки множественного наследования в Java сделало проблему невероятно сложной для классов, которые уже должны расширять что-то еще.
Интерфейсы не будут работать, насколько я могу судить, потому что интерфейсы не позволяют вам фактически реализовать методы, которые вы в них вводите.
Я рассматривал возможность добавления дополнительных аргументов к методу, чтобы заставить их работать из класса статических утилит, но это приводит к тому, что вызовы методов переходят от debug(String)
к к MessageUtil.debug(Plugin, String)
, что намного более громоздко, чем хотелось бы.
Я рассматривал возможность создания объекта Messenger, который может обрабатывать эти сообщения, чтобы я мог вызывать messenger.debug(String)
, что лучше, но я не могу избавиться от ощущения, что должен быть лучший способ debug(String)
уединиться.
Любой совет?
РЕДАКТИРОВАТЬ: эти методы, к сожалению, нельзя сделать статическими без добавления дополнительных параметров; поэтому статический импорт не будет работать.
РЕДАКТИРОВАТЬ: вот пример одного из методов, которые я пытаюсь использовать в нескольких классах. Как вы можете видеть по использованию нестатических глобальных переменных, таких как «плагин» и «отладчики», его нельзя сделать статическим.
protected myPlugin plugin;
private myList<String> debuggers = new myList<String>();
public void debug(String message) {
if (debuggers.size() == 0)
return;
if (debuggers.contains("\console")) {
plugin.getServer().getConsoleSender().sendMessage(plugin.getColor() message);
if (debuggers.size() == 1)
return;
}
for (Player player : plugin.getServer().getOnlinePlayers())
if (debuggers.contains(player.getName()))
player.sendMessage(plugin.getColor() message);
}
Вот еще один пример, который отправляет сообщение каждому игроку на сервере и на консоль, используя те же глобальные переменные, что и выше:
public void broadcast(String message) {
for (Player player : mCL.getServer().getOnlinePlayers())
player.sendMessage(plugin.getColor() message);
mCL.getServer().getConsoleSender().sendMessage(message);
}
РЕДАКТИРОВАТЬ: broadcast()
приведенный выше метод на самом деле не является статическим; это была ошибка копирования-вставки. Я изменил его, чтобы отразить это.
Комментарии:
1. Если вы считаете, что отсутствие множественного наследования классов является проблемой, вам действительно следует внимательно взглянуть на свою иерархию классов. Множественное наследование не должно быть чем-то, на что вы полагаетесь / нуждаетесь в Java, по большей части.
2. Как бы вы посоветовали мне изменить его, чтобы избежать множественного наследования? Я не хочу полагаться на множественное наследование (поскольку я не могу его использовать), но я не знаю другого хорошего способа.
3. Предпочитайте композицию наследованию.
4. Вы против статического импорта?
5. Вполне
broadcast()
может быть импорт-статический как есть.debug()
Похоже, что ваш метод имеет довольно много состояний. ПередайтеMessageUtil
экземпляр своим абонентам или используйте синглтон.
Ответ №1:
Учитывая
это заставляет вызовы методов переходить от debug(String) к MessageUtil.debug(Plugin, String), что намного более громоздко, чем хотелось бы.
Предполагая, что ваши методы являются статическими или могут быть сделаны статическими, вы могли бы использовать static import
—
import static mypackage.MessageUtil.debug;
//
debug("Hello");
Комментарии:
1. Это хорошая идея, но, к сожалению, здесь она не сработает. Я не могу сделать методы статическими, не добавляя все больше и больше параметров. Я использовал статический импорт для других вещей, которые можно было бы сделать статическими, но здесь это не работает.
2. @REALDrummer Пожалуйста, отредактируйте свой вопрос, и что вы имеете в виду под лучшим способом
debug(String)
уединения ? Чтоdebug(String)
делать?3. @ElliottFrisch OP прокомментировал в комментариях к вопросу функцию этих методов
4. @ElliottFrisch Я редактирую вопрос, чтобы отразить это.
debug(String)
предназначен для отправки данного сообщения (строки) любому, кто в данный момент находится в «режиме отладки», а не кому-либо еще.
Ответ №2:
Интерфейсы не будут работать, насколько я могу судить, потому что интерфейсы не позволяют вам фактически реализовать методы, которые вы в них вводите.
Взгляните на одну из новых функций Java 8: методы по умолчанию в интерфейсе. Может быть, вы можете что-то с этим сделать.
Комментарии:
1. Я видел это, и это было бы именно то, что мне нужно. Однако это плагин, написанный для работы с уже существующей Java-программой, которая, как я полагаю, не поддерживает Java 8. Я проведу дополнительные исследования, чтобы узнать, смогу ли я заставить его работать с Java 8. Если они поддерживают Java 8, то это было бы идеально.
2. @REALDrummer На самом деле это ничем не отличается от решений для статического импорта (если вы не собираетесь их переопределять). Я не понимаю, как это может вам помочь, поскольку вы упоминаете, что используете нестатические глобальные переменные , с которыми интерфейсы и методы по умолчанию вам не помогут. Как упоминалось в комментариях, композиция — лучший способ, или с помощью синглтона.
3. @ggovan С помощью методов по умолчанию я мог бы создать класс со всеми глобальными переменными и статическими методами, которые принимают дополнительные параметры, которые я не хочу использовать постоянно. Затем я могу создать интерфейс с методами по умолчанию, которые используют эти статические методы, но передают глобальные переменные из класса в качестве необходимых дополнительных параметров. Тогда все классы, которые я хочу, могут реализовать этот интерфейс и иметь все методы без дополнительных параметров и без композиции. Это не самое красивое решение, но оно работает.
4. @ggovan О, и это не будет работать со статическим импортом, потому что методы, которые я хочу использовать, не могут быть статическими. Я работаю в интерфейсе плагина с всеобъемлющим API с множеством вещей, которые должны быть постоянными, но могут и не быть. Это все очень сложно и странно, но это означает, что я, к сожалению, не могу сделать эти методы статическими.