When to use or how to use Multiple Bound in generics - java

I am new to generics and learning generics from hear
https://docs.oracle.com/javase/tutorial/java/generics/bounded.html
I am learning about Multiple Bounds
what I understood is you can specify class like follows
class D <T extends A & B & C> { /* ... */ }
D<A> d = new D<>();
only if A does implements B and C both
other wise compile time error will ocur
also B and C should be Interface other wise //interface is expeced compile time error will occurs
I am not talking about wildcards
My problem is I am not getting any real programing use of this.
I am finding a way/example how can i use Multiple bound generics while codding.
When should I use it?
thanks

Consider the following snippets:
class SpineWarmCollection <T extends Vertebrate & Warmblooded> { /* ... */ }
class Mammal extends Vertebrate implements Warmblooded {}
class Bird extends Vertebrate implements Warmblooded {}
class Reptile extends Vertebrate {}
SpineWarmCollection<Mammal> mammalCollection = new SpineWarmCollection<>();
SpineWarmCollection<Bird> birdCollection = new SpineWarmCollection<>();
SpineWarmCollection<Reptile> reptileCollection = new SpineWarmCollection<>(); // Generates a compile error, since Reptiles are not warmblooded.
Vertebrate is a class in animal taxonomy; however, warmbloodedness is a trait. There's no single ancestor class for warmblooded-ness, since both Mammals and Birds are warmblooded, but their common ancestor, Vertebrate, is not.
Since T can only be a class that extends Vertebrate and Warmblooded, the generic can access any methods declared in Vertebrate and Warmblooded.
You don't even need a class. T could extend interfaces only, which would allow a generic to be used by any sets of classes that implement the interfaces, even of those sets of classes are completely unrelated to one another.

Related

type of object while implementing interface

Below is my code...
Its not that much complex.
Here I want to understand that In class D, b is an interface type variable and in that variable we are storing reference to new object of class(C) which implements that interface(B). How we are able to assign object of type C to interface B type variable b..? Class and Interface both are of different types then what makes it special when we implements a interface on class and we are able to do it which is my question
public interface A {
}
public interface B {
public A methodABCD();
}
public class C implements B {
final A typeA;
public A methodABCD() {
return typeA;
}
}
public class D {
static private B b;
static public A methodABCD() {
if (b == null) {
b = new C();-------------->How..?
}
return b.methodABCD();
}
}
Ok lets take an Example and illustrate it.
interface Animal {
public void eat();
}
class Human implements Animal{
public void eat(){
// Eat cakes and Buns
}
}
class Dog implements Animal{
public void eat(){
// Eat bones
}
}
Now let see how you can use them
Animal h = new Human();
Animal d = new Dog();
Now at some point you might want to change your Human to behave like a Dog.
h =d;
h.eat();// Eat bones
Your thought became a possibility because, they belongs to the same type. Imagine that there is not Animal interface and see how difficult it is convert a Human to Dog.
You see the flexibility and the advantages in type varying. You are allowed to do that because of they both are Animal nothing but an Interface.
This is valid
B b = new C();
only because C implements the interface B, so you are telling the compiler:
"I need an object B that can do something instead of that is something...", this approach is called programming to interfaces and allows you to latter change the class C for a class F as long as F can do something too, that is a more flexible design...
Java hides the memory addresses of the objects created in Heap. Objects are accessed by the references. One object may have multiple references. Using = operator references are made to refer to an object and using . operator references can invoke a particular behavior of the object. References and objects are stored in different memory locations.
If there is an objext X of class C then as per the Java language specifications an X can have references whose type is C or any super class in higher hierarchy or any interface implemented by C or any of the super class in higher hierarchy or any interface extended by any of these interfaces.
class A implements IA{}
class B extends A implements IB{}
interface IC extends IA{}
interface IB extends ID{}
class E{}
class F extends B{}
Now new B() can have references of type A,B,IA,IB,ID but can not have reference of type E,IC,F as these do not belong to the higher lever hierarchy.
You can use interface as a reference type in java.
It can only refer to objects of those classes that implement that interface.
But remember with interface as reference you can access only those methods that are declared in that interface. Your class may define additional methods but that won't be accessible using the interface reference.
In a way when you say class and interface are of different type you are right but when a class implements an interface it provides definition to all the methods declared in that interface and hence that interface can refer to the implementing class object.
It is kind of like with inheritance.
When a class implements an interface it is bound under a contract to provide implementation to all the methods.
So when a interface refers to a class object you can be pretty sure that that class must have implemented that interface and hence all your methods declaration now have definitions that can be called.
It is because of one of the design principles, Liskov Substituion Principles, L out of SOLID,
if B is a subtype of P, then objects of type P can be replaced with instantiations of type B. Search SOLID design principles on google for more details. An object oriented language follows this

java generic bound type-why does extends only mean extending the classes and implementing the interface?

I am learning generic types in Java now. To restrict the type argument passed to the type parameter, we use the keyword "extends". It means to either "extends"(as in class) or "implements" (as in interfaces). I don't understand why it can't mean to "extends" the the interface?
Interface only extends another interface ... class implements the interface
the only class that extends the interface will be the abstract class
Yes, you can use an interface when specifying (what's the right term?) a generic type (I had to answer to post the code):
class MyGeneric<T extends MyBaseInterface> {
}
interface MyBaseInterface {
}
interface MySubInterface extends MyBaseInterface {
}
public class GenericsTest {
private MyGeneric<MySubInterface> x = new MyGeneric<>();
}
As I said in my comment above, in <T extends X> "extends" is just a way to require that T is a subtype of X (where X can be a class or an interface).

Java inheritance; passing a subclass to an abstract method of a superclass

Sorry for the title, couldn't come up with anything clearer.
I have the following structure:
public interface Vehicle {...}
public class Car implements Vehicle {...}
then:
public abstract class Fixer {
...
abstract void fix(Vehicle vehicle);
...
}
and would like to have:
public class CarFixer extends Fixer {
void fix(Car car) {...}
}
but this doesn't work. Eclipse says: The type CarFixer must implement the inherited abstract method Fixer.fix(Vehicle). Any idea how can I solve this?
You can use Generics to solve this:
public abstract class Fixer<T extends Vehicle> {
abstract void fix(T vehicle);
}
public class CarFixer extends Fixer<Car> {
void fix(Car car) {...}
}
The problem with your original version is that the fix method allows any type of vehicle, but your implementing class allows only cars. Consider this code:
Fixer fixer = new CarFixer();
fixer.fix(new Bike()); // <-- boom, `ClassCastException`, Bike is a vehicle but not a car
You've met the humble home of generics.
Generics provide kind of 'wildcard' type where a class or method can specify that 'we don't really care what type it is, we just need -a- type'.
Generics allow a super class to enforce a specific type in a child class instead of allowing any class that extends a certain class.
This means that you're ultimately enforcing a new highest allowed super-class as the parameter (i.e. Vehicle is no longer the most basic allowable type you can pass to fix(); it's now whatever the subclass says it is, so long as that arbitrary type extends Vehicle).
Common places for generics are container classes (i.e. List, Map, and Set) where the container doesn't really care about what type it tracks, but rather focuses on actually tracking and managing those instances.
Generics consist of one or more type placeholders (in Java, E and T are commonly used but the name doesn't really matter; they usually follow the normal type naming conventions) that are used in place of a specific class or super class.
In your code, you want subclasses to implement methods given their exact relevant types (i.e. a CarFixer would take Cars, a JetpackFixer would take Jetpacks) but you want to enforce that these types extend Vehicle.
In order to enforce this, you have to tell the Fixer class exactly what your subclass wants.
public abstract class Fixer <E extends Vehicle>
{
abstract void fix(E vehicle);
}
Your subclass then extends Fixer, filling in E with the type it wants.
public class CarFixer extends Fixer<Car>
{
#Override
void fix(Car vehicle)
{
// ...
}
}

How do I create a List of Class objects, all of which implement a particular interface?

Let's say I have a set of classes as follows:
there is an interface Interface1, and there are two classes Class1 and Class2, both which implement Interface1.
interface Interface1 {
}
class Class1 implements Interface1{
}
class Class2 implements Interface1{}
Now, I want to create a List of classes that implement Interface1. I was trying to do something like:
List<Class<Interface1>> classes = new List<Class<Interface1>>();
classes.add(Class1.class);
classes.add(Class2.class);
But this doesn't work. I get the compiler error:
Class1.class is of type Class<Class1> and so cannot be added to the list
Is there a way to achieve what I intend to do?
Use a wildcard bounded by your interface type
List<Class<? extends Interface1>> classes = new ArrayList<Class<? extends Interface1>>();
classes.add(Class1.class);
classes.add(Class2.class);
classes.add(String.class); // won't compile

Take argument that implements several Interfaces for object creation

I have object that I want to create using object that implements two interfaces (suppose, I can't modify object's class to create third interface that will be extends two interfaces). What will be the best way to create such objects using guice?
Java does allow you to do interface combinations, i.e.
static class TL<T extends IA & IB> extends TypeLiteral<T>(){}
but you'll notice there really has to be a concrete type T which implements both of these interfaces. Java can't invent "combination types" for variables - a type must exist with an actual class file.
I was surprised to discover that it is indeed possible to do this. I suspect this is a dark corner that Guice's maintainers would suggest not going into, and it is probably not a good idea.
Things to notice about the code below:
I am actually abusing Guice's built-in safeguards by making TL subclass TypeLiteral parameterized on IA instead of TypeLiteral on T which would be correct. So in fact, this entire example probably works by accident.
It doesn't help that much. Something, somewhere finally has to specify a concrete type (the class Both) in this case. It lets you get around specifying a concrete type in the classes which use the object, but not when you bind it or if you request it directly from the injector
Almost nobody understands the TypeA & TypeB syntax with Java generics - prepare for anybody who looks at this code to be completely baffled, even some Java gurus
If you later try to use an object which only implements one of the interfaces, you could create a dynamic proxy which implements one interface and delegates to the object, but you will still need to create an interface which combines the two to give Java a type to refer to
public class X {
static final class TL<T extends IA & IB> extends TypeLiteral<IA> {}
interface IA {}
interface IB {}
static final class Both implements IA, IB {}
#Test
public void test() {
Injector inj = Guice.createInjector(new M());
Both object = inj.getInstance(Key.get(new TypeLiteral<Both>(){}));
assertNotNull(object);
Foo<Both> foo = inj.getInstance(Key.get(new TypeLiteral<Foo<Both>>() {}));
assertTrue (object instanceof IA);
assertTrue (object instanceof IB);
assertNotNull(foo);
assertNotNull(foo.obj);
}
static class Foo<T extends IA & IB> {
private final T obj;
#Inject
Foo(T obj) {
this.obj = obj;
}
}
static class M extends AbstractModule {
#Override
protected void configure() {
bind(new TL<Both>()).to(Both.class);
}
}
}
So I think the answer is, you can but you probably shouldn't.
Either inject one interface and cast to the other when needed or inject the same object twice as two different interfaces.
Both are ugly, I know, but I'd call the whole approach ugly. If you need two different interfaces a single class implements you probably haw a flaw in your object model. If one class implements two disjoint interfaces it has two different aspects and you should probably improve it's cohesion
Why not just do:
// Your original class
class AB implements IA, IB {...}
// In a Module
bind(AB.class).in(SOMESCOPE);
bind(IA.class).to(AB.class);
bind(IB.class).to(AB.class);
// In the object to be inejcted with AB
class MyClass {
#Inject IA a;
#Inject IB b;
}
In the end, you would actually have a == b, wouldn't that fit the bill?

Categories