Declaring a field extending some type - java

I am having some problems with my syntax. I am looking all over and could not find the correct thing (I actually do not know, what would be the phrase to search). So here is the problem. For simplicity, lets assume I have 4 classes:
class A:
public abstract class A{
}
class B:
public class B extends A{
//some methods and fields
}
class C:
public class C extends A{
//some other methods
}
class D:
public class D{
protected ? value;
}
Here I have a problem, because I do not know what to put instead of ? in class D, if I want to define ? as some sub-class of A. I know an option is just to write A instead of ?, but I think that this could be more specified, for example something like <T extends A>.
Is this even possible?
-edit-
From answers below, I saw that approach would be, to use raw types. But nevertheless, can anyone confirm that a construct like this, does not exist in java? That you could create a field of generic type T (extending some class), but the class containing this field does not have a generic parameter T?

Use a generic class as follows:
public class D<T extends A> {
protected T value;
}
MyClass isn't dependent of T as you pretend in your comment above. You can instantiate an instance without precising wildcard. Therefore, T would still be remplaced by A at compile-time
This concept is called: Raw types
For more information: http://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html

I think you should specific to this value Type at run time .
public class D<T extends A>{
protected T value;
}
D<B> d =new D<B>();
D<A> d1 = new D<A>();

- Use Type Parameter,
Eg:
public class MyClass<T extends A>{
T value;
}

Related

Generic class with two class hierarchies

I have the following Java generics question
I have the following generic class thay may be sketched as:
public class MyClass<T> {
AnotherClass<T> another;
OtherClass<T> other;
...
}
where ... represents code that is not relevant to the case.
For the class MyClass<T> is not as important which exact type T is (as of now) but for both:
AnotherClass<T>
OtherClass<T>
is absolutely crucial what the generic type is and decisions will be made at runtime in base of that.
Based on that, the type T is not completely arbitrary, it may be either an instance of a hierarchy of classes T_1 or a hierarchy of classes T_2.
As is defined the class, the type T is equivalent to Object but I know that is equivalent to either T_1 or T_2
There is not businnes relation between entities T_1 and T_2 therefore I'm not doing:
public interface BaseT { ... }
public class T_1 implements BaseT { ... }
public class T_2 implements BaseT { ... }
public class MyClass<T extends BaseT>
Clarification about why using a generic if they are unrelated:
I'm defining (trying to) a generic class for both because even they are unrelated explictly, there is a implicit relation because both T_1 and T_2 can and will appear associated to the entity represented in MyClass
T will be the same for MyClass, AnotherClass and OtherClass so that in a instance there will only be either T_1 or T_2 but never both at the same time.
My question is, which alternatives do I have here other than design an
interface for MyClass and implement it for both T_1 and T_2?.
Can I achieve something like MyClass<T extends T_1 or T_2>?
Kind regards
Probably, this is not exactly what your're looking for, but you might give it a try:
Create an abstract generic class that implements everything:
public abstract class MyClass<T>
{
AnotherClass<T> another;
OtherClass<T> other;
// Add any code needed
}
Then create 2 generic classes for both base classes.
These classes may be empty if all code can be implemented in the abstract one:
public class MyT1Class<T extends T_1> extends MyClass<T>
{
}
public class MyT2Class<T extends T_2> extends MyClass<T>
{
}
I know it's not a very good answer but I couldn't leave it as a comment to the question.
You can check the type at runtime by trying the following:
public class MyClass<T>
{
// This factory-method creates an instance of the class if the correct type is passed
// It throws a RuntimeException if not.
public static <T> MyClass<T> getInstance(Class<T> type)
{
if (T_1.class.isAssignableFrom(type) || T_2.class.isAssignableFrom(type))
return (new MyClass<T>());
else
throw new RuntimeException("Cannot create instance of MyClass<" + type.getName() + ">");
}
...
}
Then
class T_3 extends T_2
{
}
....
MyClass<T_3> test_1;
test_1 = MyClass.getInstance(T_3.class); // This will succeed
MyClass<String> test_2;
test_2 = MyClass.getInstance(String.class); // Fails

Java parameterize class warning

I want to parametirize class with two other params, so that I can provide one of them independently, AdGroupIdentifier OR KeywordIdentifier. But I am getting following warning: The type parameter KeywordIdentifier is hiding the type KeywordIdentifier.
Do you think I am doing something wrong? What is a correct way of doing that?
Thanks for any help!
public class Metrics <T extends AdGroupIdentifier, KeywordIdentifier> {
public void addMetric(T identifier){ .... }
}
It seems that you have class named KeywordIdentifier. The class parameter named KeywordIdentifier does not relate to class with the same name but can confuse humans. This is exactly what the compilation warning mean.
BTW according to naming convention you should tend to call type parameter using one (or maximum 2) capital letter. In your case change the class definition to
public class Metrics <T extends AdGroupIdentifier, K>
or, if you want the seconds parameter to extend class KeywordIdentifier:
public class Metrics <T extends AdGroupIdentifier, K extends KeywordIdentifier>
Just remove the KeywordIdentifier. It seems that AdGroupIdentifier implements or extends KeywordIdentifier:
public class Metrics <T extends AdGroupIdentifier> {
public void addMetric(T identifier){ .... }
}
Normally generic types are given one letter names as they are parameterized.
The way you have it, you might confuse KeywordIndetifier which extends Object with your class KeywordIdentifer and while they have the same name, they are not related.

Intertwined java generic interfaces and classes

I have a very specific problem with java generics. The follwowing classes and interfaces have been predefined:
public interface IFirst<R, T> {...}
public abstract class AbstractFirst<T extends AbstractFirst, L extends IFirst<String, T>> {...}
public interface ISecond extends IFirst<String, AbstractSecond> {...}
public abstract class AbstractSecond extends AbstractFirst<AbstractSecond, ISecond> {...}
Now I've created a following repo definition which seems to be valid:
public abstract class AbstractRepo<T extends AbstractFirst<T, IFirst<String,T>>> {...}
But now that i want to extend it:
public class RepoFirst extends AbstractRepo<AbstractSecond> {...}
I get the following error:
Bound mismatch: The type AbstractSecond is not a valid substitute for the bounded parameter
<T extends AbstractFirst<T,IFirst<String,T>>> of the type AbstractRepo<T>
I cannot change the first four (at least not radically) beacuse they are too heavily ingrained with the rest of the application, but the second two are new and up for change if need be.
Also intrestingly it allows the following (with raw type warnings):
public class RepoFirst extends AbstractRepo {
...
#Override
AbstractFirst someAbstractMethod() {
return new AbstractSecond() {...};
}
...
}
But for code clarity I would like to implement it with clearly defining AbstractSecond as the generic type for Abstract Repo.
What am I missing?
Your AbstractRepo expects an instance of IFirst and not a subtype of IFirst. But your AbstractSecond is clearly not IFirst. (I mean it is, from a OO standpoint but for generics, List<Number> is not the same as List<Integer>). It's ISecond. It might work if you could change your AbstractRepo from IFirst to ? extends IFirst as you did for AbstractFirst.

Inherit generic type and force the <type>

Is it possible to inherit generic type and to force in the child class the type received?
Something like:
class A<GenericType>{}
class B extends A<GenericType>{}
Or:
class B <PreciseType> extends A <GenericType>{}
But where do I define the GenericType used in B?
Given
class A<T> {}
It depends on what you try to do, but both options are possible:
class B extends A<SomeType> {};
B bar = new B();
A<SomeType> foo = bar; //this is ok
and
class B<T> extends A<T>{}; //you could use a name different than T here if you want
B<SomeType> bar = new B<SomeType>();
A<SomeType> foo = bar; //this is ok too
But keep in mind that in the first case SomeType is an actual class (like String) and in the second case T is a generic type argument that needs to be instantiated when you declare/create objects of type B.
As a piece of advice: using generics in collections is easy and straightforward, but if you want to create your own generic classes you really need to understand them properly. There are a few important gotchas about their variance properties, so read the tutorial carefully and many times to master them.
Assuming A is declared as class A<T> {} and you want be to be specialised on String only for example, you can declare it as class B extends A<String>.
Example:
public class A<T> {
public T get() {
return someT;
}
}
public class B extends A<String> {
public String get() {
return "abcd";
}
}
class B extends A<GenericType>{}
This is possible. Your B class will be a new class that extends generic A class with specific class as parameter and B will not be a generic class.
class B <PreciseType> extends A <GenericType>{}
In this case you create a generic class B which has generic parameter PreciseType. This class B extends a specific version of A, but A's parameter doesn't depend on PreciseType.
If you want to create a generic class that has a parameter which is used in specification of parent class you can use the following:
class B <PreciseType> extends A <PreciseType>{}

Multiple wildcard bounds

Suppose that I have the following class:
public class Either<A, B> {
public Object get();
}
Either is a type that stores one object of either type A or B. get() retrieves that one object.
The question is whether or not it is possible to use generics to alter the method signature of get() so that the type returned is not just Object, but any common supertype of A and B. For example, an Either<Integer, Long> can have get() return Number, an Either<Deque<T>, Set<T>> can have get() return Iterable<T> or Collection<T>, and so on. (Obviously, an Either<Foo,Foo> should have get() return Foo).
If this is at all possible, if I had Either<List<A>, List<B>>, what is the most specific type get() can return? Is it raw List, wildcard List<?>, or something else entirely?
Java inference do have something similar, we can do
public static <C, A extends C, B extends C> C get(Either<A,B> e)
{ return (C)e.get(); }
inference:
A=Integer, B=Long ==> C=Number
A=List<Integer>, B=List<Long> ==> C=List<? extends Number>
usage:
Either<Integer, Long> x = ...;
get(x); // the return type is Number
However there's probably no way to turn it into an instance method. We would need to write
public class Either<A,B>
public <C super A|B> C get() { ... }
or simply
public A|B get(){ ... }
which is not supported in Java
Why not define an abstract class C, containing as much logic common to A and B as you deem necessary, and refer to that in your Either class:
public class Either<C> {
public C get();
}
That doesn't seem like much of an answer, but since Java erases your type information anyway when compiling (that it to say, your compiled code sees only Object instead of an A or a B), then you are in the best position to define what should be retained in an explicit common class.
As far as I know, it is not possible: your Either<A,B> class makes an assumption about a generic third type (let's call it C), which both A and B would extend: while it is possible to write something like public class Either<A extends MyNonFinalClass, B extends MyNonFinalClass> {}, Java doesn't allow forward-referencing a generic type, so you cannot even write something like Either<A extends C, B extends C, C>. Clearly a shame, as your Either class would really be handy :)
You need to make sure A and B share a common ancestry.
public class Either<A extends CommonAncestor, B extends CommonAncestor> {
public CommonAncestor get() {....}
}
or
public class Either<C, A extends C, B extends C> {
public C get() {....}
}

Categories

Resources