Wednesday, May 27, 2009

How to achieve covariance in method parameters

Consider the following example:


public interface Toy {
public String getName();
}

public class SuperHeroes implements Toy {
public String getName() {
return "Spiderman";
}
}

public class Dolls implements Toy{
public String getName() {
return "Barbie";
}
}

public interface ChildrenAtPlay{
public void play(Toy toy);
}

public class Boys implements ChildrenAtPlay{
public void play(Toy toy) {
}
}

public class Girls implements ChildrenAtPlay{
public void play(Toy toy) {
}
}


Children play with toys but lets assume boys and girls play with different types of toys. The problem with the code above is that it allows boys to play with Dolls and girls to play with superheroes. If you attempt to change the code and make the play method in Boys to accept a parameter of type SuperHeroes, code will not compile, because the ChildrenAtPlay interface contract is not satisfied. So how can we provide a narrower type for a method parameter. Is it possible to have covariant parameters just like Covariant return types?
DISCLAIMER: This is only an example to illustrate a point about covariant return types. I dont subscibe to the views that boys cannot play with dolls or girls cannot play with super heroes.


You can achieve a covariant parameter using generics. Modify the interface ChildrenAtPlay to actually take a type parameter T extends Toy. Then modify the play method to accept any type of Toy. Then while defining the Boys and Girls classes specify the Toys they can play with.

Here is the code to achieve this:
    public interface ChildrenAtPlay <T extends Toy> {
public void play(T toy);
}

public class Boys implements ChildrenAtPlay <SuperHeroes> {
public void play(SuperHeroes toy) {
}
}

public class Girls implements ChildrenAtPlay <Dolls>{
public void play(Dolls toy) {
}
}

No comments:

Post a Comment