How to extend a generic class with added constraints in java? - 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)

Related

Java Generics: Class that takes a class that takes another class

I have a class BatchConfigurable
public class BatchConfigurable<T extends BatchContext>() {}
I am trying to write a wrapper for it. This will be another class that takes this class or any class that extends BatchConfigurable as parameter. For the declaration, I'm trying:
public class WrappedBatchConfigurable<E extends BatchConfigurable <T extends BatchContext>>() {}
This is invalid but as should be clear from the code, I want to preserve the property that the subtype of BatchConfigurable that WrappedBatchConfigurable takes should take a type that extends BatchContext as parameter. What would the syntax for this be?
You need to declare your type parameter T before you use it.
class WrappedBatchConfigurable<T extends BatchContext, E extends BatchConfigurable<T>> {}

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().

How to I declare a abstract generic superclass for an other generic class?

How to I declare a abstract generic superclass for an other generic class?
public class CampionsLeague<Team> extends League<Team> {
...
At League<Team> I get the error:
"Bound mismatch: The type Team is not a valid substitute for the bounded parameter < Team extends Comparable< Team>> of the type League< Team>"
As the error clearly states, you can't write League<X> unless X satisfies the constraints declared in League's declaration.
You need to constrain the derived class' generic parameter to match the constraints in the base class:
public class ChampionsLeague<Team extends Comparable<Team>> extends League<Team>
If you have generic class
class League<T extends Comparable<T>>
and you want to create its generic subclass, you have to ensure that all the constraints are satisfied:
class ChampionsLeague<T extends Comparable<T>> extends League<T>
But when you want to subclass class with provided generic type, for example there is a class:
class Team implements Comparable<Team>
you should not repeat this type in the derived class name:
class ChampionsLeague extends League<Team>
Something like this:
class ChampionsLeague<Team> extends League<Team>
class ChampionsLeague<Team extends Comparable<Team>> extends League<Team>
will be treated by compiler as hiding previous generic type of the League by a new placeholder. Fortunately, you should be warned by you IDE and you can see something like this:
The type parameter Team is hiding the type Team.

Why is implementing a generic interface so counter intuitive?

interface Foo<T extends Number>{
}
class Bar<T extends Number> implements Foo<T>{
}
Why does the class have to be written that way instead of:
class Bar<T extends Number> implements Foo<T extends Number>{
}
Surely the second way is clearer.
Because that's the same T, so it's redundant to say it extends Number again.
In the line
class Bar<T extends Number> implements Foo<T> {
T is defined at the first occurrence and used at the second. extends Number constrains the type that T can be instantiated with. You can put such constraints only at the place where T is defined.
It is similar to ordinary function parameters, where you write the type only in the declaration and not at the places where you use the parameter.

Categories