Home > Back-end >  In Java, Is it Possible to Have Two Functions with the Exact Same Signature, Except One is static
In Java, Is it Possible to Have Two Functions with the Exact Same Signature, Except One is static

Time:10-29

I am writing a class Baz<T> with function declarations similar to the following:

public SomeClass1<T> foo(T);                               // Overload #1
public SomeClass1<T> foo(T, SomeClass1<T>);                // Overload #2
public SomeClass1<T> foo(T, SomeClass1<T>, SomeClass1<T>); // Overload #3

Since #1 is the only function that uses this, I could make all the others static:

public SomeClass1<T> foo(T);
public static <T> SomeClass1<T> foo(T, SomeClass1<T>);             //#2 and #3 now static
public static <T> SomeClass1<T> foo(T, SomeClass1<T>, SomeClass1<T>);

However, that would make calling different foo overloads inconsistent. I could simply make #1 take a Baz (instead of this), but it seems that:

baz.foo(t);

is more syntactic sugar than:

Baz.foo(baz, t);

If I don't make #2 and #3 static, then there is no way to prevent something like:

Baz<Bar> baz1 = new Baz<Bar>(); // Bar is any class type; replaces T
Baz<Bar> baz2 = new Baz<Bar>();

SomeClass1<Bar> sc = new SomeClass1<Bar>(baz1); // make a SomeClass1 that is somehow attached to baz1; however, SomeClass1 does NOT keep a reference to baz1

baz2.foo(new Bar(), sc); // runs and compiles just fine!

What I ended up trying to do was to have a non-static and a static overload for each one, where the non-static overloads simply delegate to the static:

public SomeClass1<T> foo(T);                 // All non-static overloads delegate to the corresponding static overload
public SomeClass1<T> foo(T, SomeClass1<T>);             
public SomeClass1<T> foo(T, SomeClass1<T>, SomeClass1<T>);

public static <T> SomeClass1<T> foo(T, Baz<T>);     // Baz could be first or last argument
public static <T> SomeClass1<T> foo(T, SomeClass1<T>);            
public static <T> SomeClass1<T> foo(T, SomeClass1<T>, SomeClass1<T>);

I get the following error coming from the declaration of overload #2, #3, and their corresponding static overloads, replacing my-method-signature with the corresponding method signature and my-class-name with Baz<T>, or the data type I am using:

Erasure of method my-method-signature is the same as another method in type my-class-name

Questions:

  1. Is there any better option than what I am trying or want to do? Is it possible to accomplish what I am attempting? If so, how?
  2. Is what I am trying to do (i.e., make syntax consistent and make it impossible to call a method with "mismatching" SomeClass1<T> and this objects) even worth it?

P.S. Sorry for the long post.

CodePudding user response:

Yes, there is a better option: Do nothing.

There is nothing wrong with having a method that doesn’t need this to do its job. That’s an implementation choice, which has nothing to do with an instance fulfilling its contract of implementing methods.

There are plenty of commonly used design patterns that have such methods. Take the various factory patterns for example - their methods have a contract to return an instance. Nobody knows or cares if they use this to get the job done or not.

CodePudding user response:

No, you can't.

8.4.2. Method Signature Two methods or constructors, M and N, have the same signature if they have the same name, the same type parameters (if any) (§8.4.4), and, after adapting the formal parameter types of N to the the type parameters of M, the same formal parameter types.

The signature of a method m1 is a subsignature of the signature of a method m2 if either:

m2 has the same signature as m1, or

the signature of m1 is the same as the erasure (§4.6) of the signature of m2.

Two method signatures m1 and m2 are override-equivalent iff either m1 is a subsignature of m2 or m2 is a subsignature of m1.

It is a compile-time error to declare two methods with override-equivalent signatures in a class.

https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4

  • Related