So, the problem is:
I have an abstract base class (Property) which has an abstract member method (same()). The same() method returns boolean and should check for equality, but "equality" may be interpreted differently in the subclasses, therefore I am not overriding equals() or compareTo(). Because it tests for equality with another object of its type, the signature looks like that:
public abstract boolean same(Property other);
Now, when I am trying to override it in class, let's say "SubProperty", i cannot use SubProperty as the type of the parameter. I know about the reasons of this in general and the recommendation to add type bounds, but things are getting more complicated because the parameter type is its own class.
Is there any smooth way to override the method properly?
Because it was recommended in other StackOverflow questions, I tried to use type bounds (which are in this case circular). So, the class would look like this:
public abstract class Property<T extends Property<T>>
and the same() method:
public abstract boolean same(T other);
For the subclass this means:
public class SubProperty extends Property<SubProperty>
and the same()method:
public boolean same(SubProperty other);
This would be the result if I would use type bounds as recommended. It actually builds, but I don't even know if it would work properly. Anyway, it looks horrible and unmaintainable (especially because I am using 2 other generic type arguments in Property).
I hope that there is some other way to do this. If it matters, I am using java 1.8 (openjdk 1.8.0.212-b04)
EDIT 1:
Because people asked: same() is not anything like equals() or compareTo(). Yes, it is about equality in some sense. But actually I think it is easier to describe it like this:
same() is a method that checks for something in this and some other object of the same class and returns true or false according to what happened in the method.
EDIT 2:
As #davidxxx explained, it seems to be impossible to make the code any "smoother". I will probably just leave the base class parameter and check which object I got inside the method. Seems not too bad after all.
Unfortunately you don't have other ways because in Java the return type is covariant but the parameter type is not because it would be contrary to the liskov principle.
Liskov's notion of a behavioural subtype defines a notion of
substitutability for objects; that is, if S is a subtype of T, then
objects of type T in a program may be replaced with objects of type S
without altering any of the desirable properties of that program (e.g.
correctness).
Here is a simple example that shows why this rule matters.
Suppose the subclass :
public class FooProperty extends Property{
public boolean same(FooProperty other){...}
}
Suppose that you instantiate it in this way :
Property property = new FooProperty();
You can so do :
property.same(new FooProperty());
But you can also do :
property.same(new Property());
But that is not consistent in terms of expected parameter for the FooProperty.same() override that expects a FooProperty.
And that violates the liskov principle because I should be able to replace any Property instance by any subclass of that.
Only, the generic type declared on the class as in your example allows to bypass this limitation and to leave the subclass makes its mind about the subclass to use as parameter.
Anyway, it looks horrible and unmaintainable
That is very maintainable since if you refactor the class name, it will be updated.
But that is a little verbose indeed.
I think you'd just use a generic
public abstract class AbstractBase<T extends Property> {
public abstract boolean same(T property):
}
public class Concrete extends AbstractBase<SubProperty> {
public boolean same(SubProperty property) {
// TODO
}
}
Related
I have the following interface:
public interface Message<T> {
//some other methods
Class<T> getType();
}
Each implementation is always returning the class of T. For example:
public class StringMessage implements Message<String> {
//other overrides
#Override
Class<String> getType() {
return String.class;
}
}
I would like to make this getType a default method of the interface, but that's not possible since I can't call T.class because of type erasure:
public interface Message<T> {
//some other methods
default Class<T> getType() {
return T.class; //<-- not allowed
}
}
Do you know any trick to avoid having to repeat the return XXX.class on each implementation?
Note that I can't bound T to anything, it must remain unbounded.
Note 1: if the answer is no and well explained, I'll accept it.
Note 2: I found many questions that "sound like this" but are not exactly the same (they usually refer to instances and not to the static interface itself). If you find the right duplicate, don't hesitate to mark it as such and I'll delete it.
Yes. And No. It's complicated.
Before we go down this path, are you sure?
Generally, caring about the <T> in Class<T> is a code smell and means your API design is bad. For example, the T in generics can not represent primitives, but it can represent parameterized types; for example, Stream<List<? extends Foo & Bar>> is fine. An instance of java.lang.Class on the other hand can represent primitives (return int.class;), but cannot represent parameterized types. List<String>.class is not a thing, and there is no instance of j.l.Class that represents "a list of strings". List is as far as it goes.
Generally if you think you want a Class instance what you really wanted is a factory. A factory is the way to abstract away a constructor. Instead of returning a Class<T> this code should probably be wanting a Supplier<T> perhaps or some other interface-of-T that does the job of whatever you're currently using Class<?> for. If you're using that class instance for invoking .getConstructors(), then move that logic into an interface instead. Etcetera.
You've considered all that and still insist.
Generics are erased at runtime, yes, but they still exist in those places where they are part of signatures. In other words, in the extends and implements clauses of class definitions, in the types of fields, and in the parameters and return type of any method definition. The JVM considers these comments (the JVM does not know or care about generics in the slightest, it is purely something javac and editors worry about), but they are available in the class file and therefore you can theoretically at least query it.
But, and this is very important, only the literal thing that is there, at compile (write) time, is available.
So, yes, you CAN retrieve the String bit in public class StringMsg implements Message<String>. But what if you write public class GeneralMsg<T> implements Message<T>? Then all you get is T. What if you write public class ListOfStringsMessage implements Message<List<String>>? You can obtain List<String> here, but that notion cannot be conveyed in terms of a value of type java.lang.Class.
The way to do this, is to use the method .getGenericInterfaces(). But, this is a very low level method that just gets you literally what you asked for: The list of interfaces (with any type params preserved) that the class you invoked this on directly implements. Therefore, you need to write a ton of code. After all, maybe you have this:
class StringMessage implements Message<String> {}
class UnicornStringMessage extends StringMessage {}
or even
interface StringMessage implements Message<String> {}
class MyStringMessage implements StringMessage {}
You need to write lots of code to trawl through the entire class hierarchy. Hence, writing it all out in this answer is a bridge too far. This merely handles the very simplest case, and will fail on all others. So, you need to take this code and expand on it, and add:
Detect a misuse, such as writing class GenericMsg<T> implements Message<T>.
Detect hierarchy usage (or alternatively, disallow it with a proper message, if you prefer that) by way of having an interface that extends Message<Concrete>, and then having a class that implements the subinterface.
Same, but for interface SubIntf<T> implements Message<T> and then having a class Foo implements SubIntf<String>.
Same, but with the class hierarchy: class MyMsg implements Message<String> + class MySubMsg extends MyMsg.
Taking that into consideration:
default Class<T> getType() {
for (Type i : getClass().getGenericInterfaces()) {
if (!(i instanceof ParameterizedType pt)) continue;
if (!pt.getRawType().equals(Message.class)) continue;
Type param = pt.getActualTypeArguments[0];
if (param instanceof Class<?> paramC) return paramC;
}
throw new IllegalArgumentException("Programmer bug: " + getClass() + " must implements Message<ConcreteType>");
}
I have a class with a type parameter.
class MyObject<IdType> {
#Setter
#Getter
private IdType id;
}
And I thought I can add some method for conveniency so I did.
<T extends MyObject<? super IdType>> void copyIdTo(T object) {
object.setId(getId());
}
< T extends MyObject<? extends IdType>> void copyIdFrom(T object) {
object.copyIdTo(this);
}
And I just realized that I can do this.
void copyIdTo(MyObject<? super IdType> object) {
object.setId(getId());
}
void copyIdFrom(MyObject<? extends IdType> object) {
object.copyIdTo(this);
}
Are those two sets of methods are equivalent? Which way (or style) is prefer?
In your case, the two approaches are effectively equivalent. They both restrict the argument's type to MyObject<...> or a subtype.
Since your example methods return void there's no real benefit from making the method generic. The only important thing for your method is that the argument is a MyObject<...>—beyond that the real type is meaningless. Adding the ability to make the argument's type more specific adds nothing for the method's implementation and does nothing for the caller. In other words, it's irrelevant "fluff".
So for your examples, I would say prefer the non-generic option. It's cleaner and more straightforward.
However, if your methods returned the given argument back to the caller then making the method generic could prove useful; it would allow you to declare the return type as T. This opens up possibilities to the caller such as method chaining or invoking the method "inside" another method call, all based on the specific type passed as an argument. An example of this in the core library would be Objects.requireNonNull(T).
Another good case for making the method generic is mentioned by #Thilo in the comments:
Another case would be if your method takes multiple arguments. Then you can introduce a T to make sure those two arguments have the same type (instead of two distinct types that happen to [fulfill] the constraints individually).
Yes they are equivalent. Both sets of methods declare the same thing - that the method parameter must be of type MyObject<> or a compatible subtype (subclass).
The only reason to declare T in this way is if you need to refer to T elsewhere, such as the return type of the method, or if you have multiple parameters of the same type, or inside the method body.
I would always prefer the shorter, simpler, clearer version with less angle brackets to hurt the eyeballs :)
I'm reading about type inference for generics, and this code was provided as an example that fails to compile.
import java.io.*;
class LastError<T> {
private T lastError;
void setError(T t){
lastError = t;
System.out.println("LastError: setError");
}
}
class StrLastError<S extends CharSequence> extends LastError<String>{
public StrLastError(S s) {
}
void setError(S s){
System.out.println("StrLastError: setError");
}
}
class Test {
public static void main(String []args) {
StrLastError<String> err = new StrLastError<String>("Error");
err.setError("Last error");
}
}
And the explanation given in the book was:
"(It looks like the setError() method in StrLastError is overriding setError() in the LastError class. However, it is not the case. At the time of compilation, the knowledge of type S is not available. Therefore, the compiler records the signatures of these two methods as setError(String) in superclass and setError(S_extends_CharSequence) in subclass—treating them as overloaded methods (not overridden). In this case, when the call to setError() is found, the compiler finds both the overloaded methods matching, resulting in the ambiguous method call error."
I really don't understand why type S can't be inferred at compile time.
String is passed when invoking the constructor of class StrLastError,
and from the API docs, String does implement interface CharSequence,
so doesn't that mean that S for <S extends CharSequence> actually is of type String?
I've read the Java online tutorial on the topic of generics several times. I've checked "Type Inference", and Inheritance, I just don't know how the whole thing works. I really need an explanation on this question.
The points I'm stuck at are:
If the subtype can't decide S, how come the super type can decide T, because the superclass does not have an upper bound? Or does it infer that T is String because the subtype calls the supertype's constructor first?
I understand that if the Constructor is invoked as:
StrLastError<CharSequence> err = newStrLastError<>((CharSequence)"Error");
there will be no ambiguity, since it's plain method overriding then. (Or am I even wrong here?)
However, like I said in the beginning, if String is passed, why can't S be inferred to be String?
You have to remind yourself that the classes are compiled one by one. Java generics are not templates as in other languages. There will only be one compiled class and not one class per type it is used with.
This way you can see that the class StrLastError will need to be compiled in a way such that it can also be used with other classes implementing CharSequence as generic type S.
Thats why the compiler gets you two different methods instead of an overridden one. Now it would be a runtime-job to see that the subclass may have wanted to override the method in the parent just in those cases where the types suggest it. Since this behaviour is hard to understand for the developer and would possibly lead to programming mistakes, it raises an exception.
If you use CharSequence as the generic type parameter of the class StrLastError, you will call the setError method in the parent class, since the type of "Last Error" is String, which is more specific than CharSequence and Java always chooses the most specific method in case it is overloaded. (I hope it is clear the the method was not overridden in this case either)
If the subtype can't decide S, how come the super type can decide T, because the superclass does not have an upper bound? Or does it infer that T is String because the subtype calls the supertype's constructor first?
The super type isn't deciding or inferring what T is; you're explicitly telling it what T is by this declaration:
class StrLastError<S extends CharSequence> extends LastError<String>
T is now bound to String for LastError, which makes every reference to T in the parent class a concrete String.
Your child class now has a bound S extends CharSequence attached to it, but this is independent to the bounds applied to the parent class.
What happens now is that Java will compile your child class, and the result of your child class is that two methods with a signature that matches String will be created. (Key note here: A String is-a CharSequence.)
In your child class, setError(Ljava/lang/CharSequence;)V is generated as the signature for setError. Because of the way generics work, LastError#setError will be treated as if it has a signature of setError(Ljava/lang/String;)V. This is also why when you go to actually override the method, it will place a String type as your parameter instead of anything else.
So, what we arrive at are two methods that have override-equivalent signatures.
void setError(CharSequence s)
void setError(String s)
JLS 8.4.8.4. applies here.
It is possible for a class to inherit multiple methods with
override-equivalent signatures (§8.4.2).
It is a compile-time error if a class C inherits a concrete method
whose signature is a subsignature of another concrete method inherited
by C. This can happen if a superclass is generic, and it has two
methods that were distinct in the generic declaration, but have the
same signature in the particular invocation used.
I understand that if the Constructor is invoked as StrLastError err = new StrLastError<>((CharSequence)"Error"); there will be no ambiguity, since its plain method overriding then.(Or I'm even wrong here)
No, now you're messing with raw types. Interestingly enough it will work, primarily because the signatures for the two methods has become:
void setError(Object s)
void setError(String s)
You want to use generics to avoid a scenario like this; you may want to invoke the super class method at some point, but in this scenario with these bindings, it's very difficult to accomplish.
This is a tricky example, to fix it you need to change the following line:
class StrLastError<S extends CharSequence> extends LastError<S>
I have recently started reading Core Java. But I am having a hard time grasping the concept of wildcards.
Specifically, I'm confused about the difference between the following:
public class A<T extends {some_class}> {/*...*/}
and
public class A<? extends {some_class}> {/*...*/}
Can anyone help me understand the difference if there is at all?
The difference is that you cannot use the ? elsewhere while you can use T. For example:
public class Foo<T extends Number> {
T value; // you can declare fields of type T here
int foo() {
// Since you said T extends Number, you can call methods of Number on value
return value.intValue();
}
}
So why would you use ? at all? If you don't need the type. It wouldn't make sense to use it in a class definition any way that I can think of. But you could use it in a method like this:
int getListSize(List<?> list) {
return list.size();
}
Any kind of method where you're more interested in the overall class and it has a method that doesn't involve the paramaterized type would work here. Class.getName() is another example.
They are the same, except with the wildcard you can't refer to the type in the code of your class. Using T names the type.
In generic code, the question mark (?), called the wildcard, represents an unknown type. The wildcard can be used in a variety of situations: as the type of a parameter, field, or local variable; sometimes as a return type (though it is better programming practice to be more specific). The wildcard is never used as a type argument for a generic method invocation, a generic class instance creation, or a supertype.
The Type T is a defined type or known type
Hope this helps
? extends some class or T extends some_class
means some_class itself or any of its children and anything that would work with instanceof some_class.
As per conventions T is meant to be a Type and ? is unknown type.
I saw this pattern somewhere:
class A extends B<A> {
}
This structure is a little unusual to extend a generic by specifying the new type as actual type of generic. What is the use? Is there a name for this pattern? Is there any alternative pattern?
Example: https://code.google.com/p/selenium/wiki/LoadableComponent
Jump to: public class EditIssue extends LoadableComponent<EditIssue> {
Edit:
After reading the responses, it seems that I need to alter my understanding of type checking by the compiler. At the back of my mind, my beef with this pattern was, if the two A's need to be same then is there a way to not repeat them? But it seems that there is no better way to propagate the derived class's type to the parent.
Of course the OOP answer is that A is a B. If A were not a B than A should merely compose itself with a B to make use of B's functionality.
Presumably B also has some general implementations which take advantage of restrictions placed on the generic type.
Another use case would be for B to look something like:
abstract class B<T extends B<T>> {
public T createCopy(T t);
}
Now subclasses can implement createCopy and client code can safely use it without having to cast... e.g.
class A extends B<A> {
public A createCopy(A t) {
return new A(t); //copy constructor
}
}
Compare the above to:
abstract class B {
public B createCopy(B t);
}
class A extends B {
public B createCopy(B t) { //Is the copy an A or a different subtype of B? We don't know.
return new A(t); //copy constructor
}
}
You might do something like this when dealing with recursive data structures. For example, nodes in a graph or a tree could be defined as a collection of other nodes:
class Node extends AbstractList<Node> {
...
}
Equally you might see something like this if the abstract/generic type is meant for comparing objects of a similar type, such as is the case with java.lang.Comparable:
class MyObject implements Comparable<MyObject> {
public int compareTo(MyObject other) { ... }
}
Take this example:
E extends Comparable<E>
This means that E must be a type that knows how to compare to itself, hence, the recursive type definition.
Don't know if it has any official names, but I would call it recursive generic type pattern.
It is indeed perplexing, since the two types A and B<A> appear to rely on each other to exist; that doesn't make much sense in ordinary OOP, so what is it for? I found 3 use cases for this pattern.
Composition turned Inheritance
Say a Node has a list of child Nodes. The usual design is through composition
class Node
ArrayList<Node> children = ...
Sometimes for a small performance gain, people use inheritance instead
class Node extends ArrayList<Node>
// the super class represents the children...
This is a little confusing, but there's nothing hard to understand. We know it's just a convenience, it does not try to convey that a node is a list of nodes.
LoadableComponent can be considered of this use case. It's arguably a less ideal design than a composition approach
class ComponentLoader<C>
C get(){...}
class EditIssue
final ComponentLoader<EditIssue> loader = new ComponentLoader<EditIssue>(){
#Override void load(){...}
#Override void isLoaded(){...}
};
EditIssue compo = ...
compo.loader.get().doSomething();
The designer might find this approach more boiler platey.
Method Chaining
Instead of writing
foo.doA();
foo.doB();
a lot of people would rather want to write
foo.doA().doB();
Unfortunately the language doesn't directly support method chaining even though it is becoming an increasingly desired feature. The workaround is for doA() to return foo. It is a little dirty but acceptable.
However if foo is in a type hierarchy the workaround is broken
class Bar
Bar doA()
class Foo extends Bar
Foo doB();
foo.doA().doB(); // doesn't compile, since doA() returns Bar
So some people call for a special "self type" to solve this problem. Let's say there's a keyword This to represent "self type"
class Bar
This doA()
foo.doA().doB(); // works, doA() returns the type of foo, which is Foo
It appears that method chaining is the only use case for "self type", so the language probably will never introduce it (it's better to just support method chaining directly)
People found out that generics provides a workaround for this problem
class Bar<This>
This doA()
class Foo extends Bar<Foo>
Foo has a method "Foo doA()", inherited from Bar<Foo>
This is the most popular use case for the A extends B<A> pattern. It is an isolated workaround/trick. It adds no semantics in relationship between A and B.
It is also a popular practice to constraint This like
class Bar<This extends Bar<This>>
It is ugly and useless, I strongly recommend against it. Simply use "This" as a convention to indicate what it is for.
LoadableComponent can also fall in this use case. In a simpler design we could do
class LoadableComponent
void ensureLoaded()
class EditIssue extends LoadableComponent
EditIssue compo = ...
compo.ensureLoaded();
compo.doSomething();
To support method chaining of the last two lines, LoadableComponent is designed in its current form, so that we can write compo.get().doSomething()
Something more meta
So the previous two use cases are kind of hacks. What if there's a genuine constraint between A and B<A>?
Rather than serving as an ordinary super type, B is more meta, it describes that a type A should have some properties that reference A itself. This is not inheritance in traditional OOP's sense, it is something more abstract. (Though it is still implemented through traditional inheritance mechanism, it's imaginable that the language can promote it as a standalone concept.)
Comparable is of this use case. It describes that a certain type can compare to itself. Since it is not a traditional OOP type, ideally we should never declare an object with static type Comparable. We don't see it in public method return/parameter type, it won't make much sense. Instead we see things like
<T extends Comparable<T>>
void sort(List<T>)
here the method requires a type that conforms to the Comparable pattern.
(I don't really know what I'm talking about in this section)
This pattern is the same as any other sub-class. What's really happening when a generic is used is the JVM is creating a copy (not actually a copy, but it's kinda-sorta like that) of a class, and replacing all the spots where the generic is used with the specified type.
So, to answer your question, all that pattern is doing is substituting B<A> for B in which all the uses of A are substituted with whatever class A is. Potential uses for this are in cases where you are customizing a data structure (from java.util.Collections) for a specific class, such as using bitshifts to compact a Collection<Boolean> into a smaller amount of memory. I hope that makes sense!