Does it make sense to have a non static method whi

2020-05-24 20:42发布

问题:

The compiler does not let a static method call a non static method. I understand it does this because a not static method usually ends up using an instance variable.

But does it make sense to have a non static method which does not use an instance variable. If we have a behavior which does not affect or isn't affected by the instance state , shouldn't such a method be marked as static.

回答1:

Often times, no. If the method doesn't touch any instance state, there's no reason to tie it to an instance.

Of course, static methods can't be inherited or overridden, so that's one obvious time that you would want to have an instance method that doesn't use instance state. The strategy pattern is a classic example of this.

Another case where you may tie it to an instance anyway is if this is a public API and you imagine that you may want to tie the method to instance state in the future. In that case, backwards compatibility concerns for people who are using your API may make it difficult (or impossible) to turn that static method into an instance method.



回答2:

Well sure! Let's assume that you have in interface IMyCollection. It has a method boolean isMutable().

Now you have two classes, class MyMutableList and class MyImmutableList, which both implement IMyCollection. Each of them would override the instance method isMutable(), with MyMutableList simply returning true and MyImmutableList returning false.

isMutable() in both classes is an instance method that (1) does not use instance variables, and (2) does not affect instance state. However, due to constraints in the language (it's impossible to override static methods), this design is the only practical one.

Also, I would like to clear up a misconception (as @manouti did as well): non-static methods aren't instance because they use any instance variables or affect instance state; they're instance methods because they were defined that way (without the static keyword), and thus have an implicit this parameter (which, in languages like Python, is actually explicit!).



回答3:

Because static methods cannot be overridden, many developers that are concerned about testability of their code try to avoid static methods in Java altogether.

Code is more testable if dependencies can be replaced with mock objects. Mockito and EasyMock are the most common tools to help with this, and they rely on inheritance to create subclasses that allow you to easily override the (often complex) method that you don't want to test ... so that your test is focused on what you do want to test.

I don't go to the extreme of trying for zero static methods, but when I concede to include them, I often regret it later, for testing reasons.

All of this is very frustrating, because it has nothing to do with what ought to be the design consideration of static vs instance methods. Which makes me wish for those languages that allow you have have functions that aren't connected with a class ...



回答4:

If one were writing a human-readable description of the method's purpose, would it make mention of an object? If so, use an instance method. If not, use a static method. Note that some methods might be described either way, in which case one should use judgment about which meaning is better.

Consider, for example, "Get the address to which a Freedonian income tax form should be mailed" vs "Get the address to which Freedonian income tax forms should be mailed"? The first question should be answered by an instance method; the second by a static method. It may be that Freedonia presently requires all tax forms to be sent to the same address (in which case the former method might ignore all instance fields), but in future may have different offices for people in different regions (in which case the former method might look at the taxpayer ID and select a mailing address based upon that, while the latter method would have to direct forms to an office which could accept forms for anyone and redirect them as needed).



回答5:

I understand it does this because a not static method usually ends up using an instance variable.

Even if the instance method does not use an instance variable, it is still bound to the instance of the class. In fact, it has a reference to this implicitly in the method arguments.

In other words, in the following method:

public void foo() {

}

this is implicitly passed as the first local variable in the method.

EDIT:

Re-reading the question, it's more of a broad question that depends on the situation. Generally if the method does not need the instance (and you're pretty sure it won't), then just make it static.



回答6:

A nice example is an object-oriented encoding of booleans. Most languages, even object-oriented ones like Java, opt for an Abstract-Data-Type-oriented encoding of booleans, but e.g. Smalltalk uses an OO encoding, and almost none of the methods make use of any instance state. It looks a bit like this:

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
  }
}

In fact, if you follow a serious commitment to OO, use a lot of referentially transparent methods, and favor polymorphism over conditionals, you will often end up with methods in lots of subclasses, where each implementation in one of the classes returns a constant value.



回答7:

I think sometimes it is yes,because non static method can override to do different tasks for different class,but the task may not involve instance variable,e.g.:

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");
    }
}

print info of object:

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