Подтвердить что ты не робот

Должны ли вспомогательные классы/утилиты быть абстрактными?

Я обычно обнаруживаю, что я извлекаю общее поведение из классов в классы helper/utility, которые не содержат ничего, кроме набора статических методов. Я часто задавался вопросом, следует ли объявлять эти классы абстрактными, так как я не могу думать о действительной причине когда-либо создавать их?

Какими бы "за" и "против" было объявить такой класс абстрактным.

public [abstract] class Utilities{

   public static String getSomeData(){
       return "someData";
   }

   public static void doSomethingToObject(Object arg0){
   }
}
4b9b3361

Ответ 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 добавляет их автоматически во время компиляции.