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

Имеет ли смысл иметь нестационарный метод, который не использует переменную экземпляра?

Компилятор не позволяет статическому методу вызывать нестационарный метод. Я понимаю, что это происходит потому, что не статический метод обычно заканчивается использованием переменной экземпляра.

Но имеет ли смысл иметь нестационарный метод, который не использует переменную экземпляра. Если у нас есть поведение, которое не влияет на состояние экземпляра или не влияет на него, не следует ли помечать такой метод как статический.

4b9b3361

Ответ 1

Часто, нет. Если метод не касается какого-либо состояния экземпляра, нет причин привязывать его к экземпляру.

Конечно, статические методы нельзя унаследовать или переопределить, так что одно очевидное время, когда вы захотите иметь метод экземпляра, который не использует состояние экземпляра. Стратегический шаблон является классическим примером этого.

Другой случай, когда вы можете связать его с экземпляром в любом случае, - это публичный API, и вы предполагаете, что в будущем вы захотите связать этот метод с состоянием экземпляра. В этом случае проблемы обратной совместимости для людей, которые используют ваш API, могут затруднить (или невозможно) превратить этот статический метод в метод экземпляра.

Ответ 2

Ну конечно! Предположим, что у вас есть interface IMyCollection. Он имеет метод boolean isMutable().

Теперь у вас есть два класса: class MyMutableList и class MyImmutableList, которые оба реализуют IMyCollection. Каждый из них будет переопределять метод экземпляра isMutable(), при этом MyMutableList просто возвращает true и MyImmutableList возвращает false.

isMutable() в обоих классах есть метод экземпляра, который (1) не использует переменные экземпляра, и (2) не влияет на состояние экземпляра. Однако из-за ограничений в языке (это невозможно переопределить статические методы), этот дизайн является единственным практическим.

Кроме того, я хотел бы прояснить неверное представление (как это сделал @manouti): нестатические методы не являются экземплярами, потому что они используют любые переменные экземпляра или влияют на состояние экземпляра; они являются методами экземпляра, потому что они были определены таким образом (без ключевого слова static) и, следовательно, имеют неявный параметр this (который на языках, подобных Python, на самом деле явный!).

Ответ 3

Поскольку статические методы не могут быть переопределены, многие разработчики, которые обеспокоены тестируемостью своего кода, стараются вообще избегать статических методов в Java.

Код более подвержен тестированию, если зависимости можно заменить макетными объектами. Mockito и EasyMock являются наиболее распространенными инструментами, помогающими в этом, и они полагаются на наследование для создания подклассов, которые позволяют вам легко переопределить (часто сложный) метод, который вы не хотите тестировать... чтобы ваш тест был сфокусирован на то, что вы хотите проверить.

Я не пытаюсь использовать статические методы, но когда я соглашаюсь их включить, я часто сожалею об этом позже, чтобы проверить причины.

Все это очень расстраивает, потому что это не имеет никакого отношения к тому, что должно быть рассмотрением дизайна методов static vs instance. Это заставляет меня хотеть те языки, которые позволяют вам иметь функции, которые не связаны с классом...

Ответ 4

Если бы кто-то писал удобное для человека описание цели метода, он бы упоминал об объекте? Если это так, используйте метод экземпляра. Если нет, используйте статический метод. Обратите внимание, что некоторые методы могут быть описаны в любом случае, и в этом случае следует использовать суждение о том, какой смысл лучше.

Рассмотрим, например, "Получите адрес, по которому должна быть отправлена ​​форма подоходного налога с Фридонином", и "Получить адрес, по которому должны быть отправлены формы налога на прибыль Фридона"? На первый вопрос должен отвечать метод экземпляра; второй - статическим методом. Возможно, сейчас Freedonia требует, чтобы все налоговые формы отправлялись по одному и тому же адресу (в этом случае первый метод мог игнорировать все поля экземпляров), но в будущем могут иметь разные офисы для людей в разных регионах (в этом случае прежний метод может посмотреть идентификатор налогоплательщика и выбрать почтовый адрес на основе этого, в то время как последний метод должен будет направлять формы в офис, который может принимать формы для всех и перенаправлять их по мере необходимости).

Ответ 5

Я понимаю, что это делает это, потому что нестатический метод обычно заканчивается использованием переменной экземпляра.

Даже если метод экземпляра не использует переменную экземпляра, он все еще привязан к экземпляру класса. Фактически, он ссылается на this неявно в аргументах метода.

Другими словами, в следующем методе:

public void foo() {

}

this неявно передается в качестве первой локальной переменной в методе.

EDIT:

Перечитывая вопрос, это более широкий вопрос, который зависит от ситуации. Как правило, если методу не нужен экземпляр (и вы уверены, что этого не произойдет), тогда просто сделайте его static.

Ответ 6

Хорошим примером является объектно-ориентированное кодирование булевых элементов. Большинство языков, даже объектно-ориентированных, таких как Java, выбирают кодировку с буфером, ориентированную на абстрактные данные, но, например, Smalltalk использует OO-кодировку, и почти ни один из методов не использует какое-либо состояние экземпляра. Это выглядит примерно так:

import java.util.function.Supplier;
@FunctionalInterface interface Block { void call(); }

interface Bool {
  Bool not();
  Bool and(Bool other);
  Bool or(Bool other);
  <T> T ifThenElse(Supplier<T> thenBranch, Supplier<T> elseBranch);
  void ifThenElse(Block thenBranch, Block elseBranch);

  static final Bool T = new TrueClass();
  static final Bool F = new FalseClass();

  class TrueClass implements Bool {
    public Bool not() { return F; }
    public Bool and(Bool other) { return other; }
    public Bool or(Bool other) { return this; }
    public <T> T ifThenElse(Supplier<T> thenBranch, Supplier<T> elseBranch) {
      return thenBranch.get();
    }
    public void ifThenElse(Block thenBranch, Block elseBranch) {
      thenBranch.call();
    }
  }

  class FalseClass implements Bool {
    public Bool not() { return T; }
    public Bool and(Bool other) { return this; }
    public Bool or(Bool other) { return other; }
    public <T> T ifThenElse(Supplier<T> thenBranch, Supplier<T> elseBranch) {
      return elseBranch.get();
    }
    public void ifThenElse(Block thenBranch, Block elseBranch) {
      elseBranch.call();
    }
  }
}

public class Main {
  public static void main(String... args) {
    Bool.F.ifThenElse(() -> System.out.println("True"), () -> System.out.println("False"));
    // False
  }
}

Фактически, если вы будете следовать серьезной приверженности OO, используйте множество ссылочно прозрачных методов и предпочитайте полиморфизм над условными выражениями, вы часто будете использовать методы во множестве подклассов, где каждая реализация в одном из классов возвращается постоянное значение.

Ответ 7

Я думаю, что иногда это да, потому что нестатический метод может переопределять различные задачи для разных классов, но задача может не включать переменную экземпляра, например:

Fruit.java

public class Fruit{
    public void printInfo(){
        System.out.println("This is fruit");
    }
}

Orange.java

public class Orange extends Fruit{
    public void printInfo(){
        System.out.println("This is orange");
    }
}

Grape.java

public class Grape extends Fruit{
    public void printInfo(){
        System.out.println("This is grape");
    }
}

распечатать информацию об объекте:

Fruit f=new Grape();
f.printInfo();