Java generics: Bound mismatch.Looking for the valid substitute - java

I have a couple of generic classes:
public interface Data<E> {}
public interface Clonable<E extends Clonable<E>> {}
public interface NaturalNumberInterface extends Data<NaturalNumberInterface> {}
public class NaturalNumber implements NaturalNumberInterface {}
public interface SetInterface<E extends Data<E>> extends Clonable<SetInterface<E>> {}
public class Set<E extends Data<E>> implements SetInterface<E> {}
When I'm trying to create the new instance of Set Set<NaturalNumber> s=new Set<NaturalNumber>(); compiler says:
NaturalNumber is not valid substitute for the type parameter <E extends Data<E>> of the type Set<E>
Maybe you can help me to find the mistake, cause I spent a long time and didn't find the solution.

I assume that your SetInterface is defined in the same way as ListInterface and Data is just interface Data<T>.
The generic argument of SetInterface is F-bounded: E extends Data<E>. In your current code NaturalNumber type extends Data<NaturalNumberInterface>. So if E is NaturalNumber, then condition is violated as it should extend more specific type Data<NaturalNumber>.
You should use F-bounds for NaturalNumberInterface as well:
public interface NaturalNumberInterface<T extends NaturalNumberInterface<T>> extends Data<T>
public class NaturalNumber implements NaturalNumberInterface<NaturalNumber>
This way it will work.

Related

In an interface, I first declare a generic that extends an interface, then a generic that extends the first generic along with another interface

For example,
public interface Foo<T extends Blackness, S extends T & Whiteness> { }
Error: Type parameter cannot be followed by other bounds
T extends Blackness and S extends T so S inherently extends Blackness. The only other contingency is that S must also extends Whiteness. Because of this restriction, S must be an extension of T but also implement the functionality of Whiteness. Because of this, you will likely have to provide the type T. It's not possible for S to have multiple bounded types, which is why a sub-interface is required that implements both. What you're trying to do doesn't make logical sense. Refer to this.
public interface Foo<T extends Blackness, S extends BlackAndWhiteness<T>> {
}
public interface BlackAndWhiteness<T extends Blackness> extends Whiteness, Blackness {
}
interface Blackness {
}
interface Whiteness {
}

Generic type subclass

I have the following generic class:
public class Evalutor<T>{
}
I would like to create the type called NumberEvalutor as follows:
public class NumberEvalutor<T> extends Evalutor<T extends Number>{ //Syntax error on token "extends", , expected
}
But I couldn't do it that way. Maybe you can advice another type-safe way?
Try with:
public class NumberEvalutor<T extends Number> extends Evalutor<T> {
}
Type parameters on class-level (like <T extends Number>) must be introduced after the class name and can be referred in the super-class/super-interface list. Otherwise, there won't be a way to (explicitly) specify their runtime value when creating class instances.
This one should work :)
public class NumberEvaluator<T extends Number> extends Evaluator<T> {
}

Extend abstract generic class with abstract class in Java

I have a base abstract class public abstract class BaseModel <T extends BaseModel<T>>. Normally, I extend this class with something like public class OtherModel extends BaseModel<OtherModel>. For some of my classes, I want to have an intermediate abstract class, such that A extends B extends BaseModel.
I'd like to be able to declare public class EndModel extends MiddleModel<EndModel>. The only way I've managed to get Eclipse to be happy is if I declare MiddleModel as public abstract class MiddleModel<T extends BaseModel<T>> extends BaseModel<T>, but this seems ugly, and now I have to add a type anywhere I declare a variable as MiddleModel, even if I don't actually care what type it is. Is there a better way to do this?
If you want to add more functionality in MiddleModel, which depends on the generic type of it, declare it like this:
public abstract class BaseModel <T extends BaseModel<T>> {}
public abstract class MiddleModel <T extends MiddleModel<T>> extends BaseModel<T> {}
public class EndModel extends MiddleModel<EndModel> {}
Note that EndModel doesn't support that extensibility. It's a trade-off, because I don't want to write new EndModel<EndModel>() but rather new EndModel().

Java subclassing issue with generic type of self-referential type

import java.util.*;
// Let's define a self-referential type:
class SelfReferential<T extends SelfReferential<T>> {}
//A complete (i.e. not parameterized) subtype of SelfReferential:
class SubclassA extends SelfReferential<SubclassA> {}
//A partial (i.e. parameterized) subtype of SelfReferential:
class SubclassB<T extends SubclassB<T>> extends SelfReferential<T> {}
//Two complete subtypes of SubclassB
class SubclassB1 extends SubclassB<SubclassB1> {}
class SubclassB2 extends SubclassB<SubclassB2> {}
//Now let's define a generic type over SelfReferential:
class Generic<T extends SelfReferential<T>> {}
//No problem creating a subtype for A, B1 or B2
class GenericA extends Generic<SubclassA> {}
class GenericB1 extends Generic<SubclassB1> {}
class GenericB2 extends Generic<SubclassB2> {}
//We can also defined a parameterize type for specific types extending SubclassB
class GenericB<T extends SubclassB<T>> extends Generic<T> {}
//However, it does not seem possible to define a non-parameterized subtype of Generic of ANY subtype of SublassB
//My goal is to provide a type alias for GenericB<? extends SubclassB<?>> to avoid
//having to mention it everywhere in the code. This is like providing an alias for ArrayList<String> using
class ArrayListOfString extends ArrayList<String> {}
//Unsucessful attempts:
//class GenericAnyB extends Generic<SubclassB> {} //ERROR: bound mismatch
//class GenericAnyB extends Generic<SubclassB<?>> {} //ERROR: bound mismatch
//class GenericAnyB extends Generic<? extends SubclassB<?>> {} //ERROR: invalid syntax: a supertype cannot specify any wildcard
//class GenericAnyB extends Generic<SubclassB<? extends SubclassB>> {} //ERROR: bound mismatch
//class GenericAnyB extends Generic<SubclassB<SubclassB<SubclassB<SubclassB<SubclassB<SubclassB>>>>>> {} // well...
//class GenericAnyB extends <T extends SubclassB<T>> Generic<T> {} //ERROR: this syntax is illegal
Bottom line, I can't specify the "reference cycle" in the extends clause.
Question: Is this a Java language limitation?
You're right that this isn't possible, just like declaring a variable with a self referencing type is impossible without wildcards or raw types. You wouldn't be able to directly instantiate a SubclassB for the same reason that you can't use it as a bound without a self-referencing type parameter.
See this post for more discussion on this limitation: Self bound generic type with fluent interface and inheritance
The bottom line is that GenericAnyB would need to be generic itself to use SubclassB as a bound:
class GenericAnyB<T extends SubclassB<T>> extends Generic<T> { }
Which just adds an extra step in the hierarchy before anything is usable:
class GenericB1 extends GenericAnyB<SubclassB1> { }
class GenericB2 extends GenericAnyB<SubclassB2> { }

How to extend a generic class with added constraints in java?

I want to extend my BinaryTree class so that only Integer parameters are accepted and I can reuse the code.
public class BinaryTree<T extends Comparable<T>>
{/*code omitted for convenience*/}
public class BinaryTreeInt<T extends Integer> extends BinaryTree<T>
{/*code omitted for convenience*/}
I get following error on compilation-
BinaryTreeInt.java:1: type parameter T is not within its bound
public class BinaryTreeInt<T extends Integer> extends BinaryTree<T>
^
1 error
Can someone guide how to write code for such inheritance?
Integer is final so what you have is
public class BinaryTreeInt extends BinaryTree<Integer>
However the type implies its is int rather than Integer
The problem stems from the following potential class:
class FunnyNumber extends Integer { }
This class does not extend Comparable<T>, so it can't be used as the base T.
In other words, extends Comparable<Integer> is not the same as extends Comparable<T>.
Your second class should not be generic at all.
You should only use generics if you want to vary the type parameter.
Here, you want a single fixed type, so you should make a normal non-generic class that extends BinaryTree<Integer>. (or just use BinaryTree<Integer> directly and don't make a separate class at all)

Categories