Должны ли вспомогательные классы/утилиты быть абстрактными?
Я обычно обнаруживаю, что я извлекаю общее поведение из классов в классы helper/utility, которые не содержат ничего, кроме набора статических методов. Я часто задавался вопросом, следует ли объявлять эти классы абстрактными, так как я не могу думать о действительной причине когда-либо создавать их?
Какими бы "за" и "против" было объявить такой класс абстрактным.
public [abstract] class Utilities{
public static String getSomeData(){
return "someData";
}
public static void doSomethingToObject(Object arg0){
}
}
Ответы
Ответ 1
Вы можете просто объявить закрытый конструктор, который ничего не делает.
Проблема с объявлением класса "abstract" заключается в том, что ключевое слово abstract обычно означает, что класс предназначен для подкласса и расширения. Это определенно не то, что вы хотите здесь.
Ответ 2
Не беспокойтесь, делая их абстрактными, но включите частный конструктор без параметров, чтобы предотвратить их создание.
Точка сравнения для заинтересованных: в С# вы должны объявить класс статическим, делая его абстрактным и запечатанным (окончательный Java) в скомпилированной форме и без какого-либо конструктора экземпляра вообще. Это также делает ошибку компиляции, чтобы объявить параметр, переменную, массив и т.д. Этого типа. Handy.
Ответ 3
Я не объявляю абстрактные утилиты, я объявляю их окончательными и делаю конструктор закрытым. Таким образом, они не могут быть подклассами, и они не могут быть созданы.
public final class Utility
{
private Utility(){}
public static void doSomethingUseful()
{
...
}
}
Ответ 4
Объявляя их абстрактными, вы на самом деле указываете другим кодам, для которых вы предназначались для этих классов. Действительно, вы правы, что нет большой разницы, но семантика здесь больше связана с интерпретацией других людей, которые смотрят на ваш код.
Ответ 5
Я бы добавил еще один шаг за пределы частного конструктора:
public class Foo {
// non-instantiable class
private Foo() { throw new AssertionError(); }
}
Бросок AssertionError
запрещает методам в том же классе создавать экземпляр класса (ну, они могут попробовать). Обычно это не проблема, но в командной среде вы никогда не знаете, что кто-то сделает.
Что касается "абстрактного" ключевого слова, я заметил, что классы утилит подклассифицированы в многочисленных случаях:
public class CoreUtils { ... }
public class WebUtils extends CoreUtils { ... }
public class Foo { ... WebUtils.someMethodInCoreUtils() ... }
Я считаю, что это сделано для того, чтобы люди не должны были помнить, какой класс утилиты включать. Есть ли недостатки в этом? Это анти-шаблон?
С уважением,
LES
Ответ 6
Как указывалось другими, создайте частный конструктор без параметров. Никто не может создать экземпляр этого объекта, кроме самого класса.
Как показали другие, как это делается с другими языками, вот как вы это делаете в следующей версии С++, как сделать класс неактивным:
struct Utility {
static void doSomething() { /* ... */ }
Utility() = delete;
};
Ответ 7
Нет, но если ваш язык поддерживает его, есть веский аргумент, который следует сделать в большинстве случаев, когда они должны быть объявлены как "статические"... Static сообщает компилятору, что они не могут быть созданы, и что все методы в них должны быть статическими.
Реферат предназначен для классов, у которых есть детали реализации на основе экземпляра, которые будут использоваться экземплярами производных классов...
Ответ 8
Вспомогательные методы просто хороши. Не беспокойтесь о добавлении их в библиотеку внутри вашего приложения или Framework. Большинство структур, которые я видел, используют их во многих вариантах.
Говоря об этом, если вы хотите получить хитрое из них, вы должны изучить методы расширения в С# 3.0. Использование метода расширения сделает ваши утилиты немного более "целостной" частью вашей структуры, которая кажется тем, что вы пытаетесь сделать, рассматривая их абстрактную. Не говоря уже о методе расширения, очень весело писать!
Ответ 9
кто-то сказал, что в С# 3.0 вы можете выполнить это с помощью методов расширения. Я не парень из С#, немного вернулся в 1.5/2.0 дня, но не использовал его с тех пор. Основываясь на очень поверхностном понимании, я думаю, что нечто подобное может быть выполнено в java со статическим импортом. Я понимаю, что это совсем не то же самое, но если цель состоит в том, чтобы просто сделать эти методы утилиты кажутся немного более "родными" (из-за отсутствия лучшего термина) вызывающему классу, я думаю, что это будет трюк. Предположим, что класс Utilities, указанный в моем первоначальном вопросе, был объявлен.
import static Utilities.getSomeData;
public class Consumer {
public void doSomething(){
String data = getSomeData();
}
}
Ответ 10
Могу ли я предложить конструктивный совет?
Если вы делаете много всего, есть две проблемы, с которыми вы столкнетесь.
Прежде всего, статический метод, который принимает параметр, часто должен быть частью объекта, являющегося этим параметром. Я понимаю, что это не помогает для таких объектов, как String, но если он принимает объекты, которые вы определили, вы почти наверняка улучшите объект, включив в него помощника как метод этого объекта.
Если он принимает все собственные значения, вы, вероятно, можете определить объект, которым он является метод. Посмотрите, можете ли вы найти группировку этих собственных значений и сгруппировать их в качестве объекта. Если вы просто попробуете это, вы найдете много других применений для этого маленького мини-объекта, и, прежде чем вы это узнаете, это будет удивительно полезно.
Другое дело, если у вас есть класс утилит с кучей полустационарных статических методов и статических переменных, вы почти всегда хотите, чтобы он был одиночным. Я обнаружил это методом проб и ошибок, но когда вы узнаете, что вам нужно больше 1 (в конце концов, вы это сделаете), намного проще сделать одноэлементный код в несколько раз (?), Чтобы попытаться изменить статический класс на несколько точек ( хорошо, поэтому я сейчас делаю слова).
Удачи. Этот материал был в основном пробным и ошибочным для меня - понял это, как и 5 лет назад, хотя, и я никогда не нашел экземпляр, где я сожалел о том, что у меня нет статического класса/методов.
Ответ 11
Я думаю, что лучше объявить служебные классы final с помощью частного конструктора без аргументов. Более того, все члены этого класса должны быть статичными.
Простой способ сделать все это в одном утверждении - использовать аннотацию @UtilityClass
для Lombok:
@UtilityClass
public class Utilities{
public String getSomeData() {
return "someData";
}
public void doSomethingToObject(Object arg0) {
}
}
Если вы используете аннотацию @UtilityClass
, вы можете пропустить статические ключевые слова, как в примере выше, поскольку Lombok добавляет их автоматически во время компиляции.