问题
Suppose I have the following interfaces
:
public interface GameObject {
void viewDetails();
}
public interface Weapon extends GameObject {
void attack();
}
//A weapon is not the only item reloadable. A container could be refilled.
public interface Reloadable extends GameObject {
void replenish (final int amount);
}
and Implementation:
public final class ReloadableWeapon implements Reloadable, Weapon {
private String weaponName;
private int numberofbullets;
public ReloadableWeapon(String name, int bullets){
this.weaponName = name;
this.numberofbullets = bullets;
}
@Override
public void replenish(final int amount) {
this.numberofbullets = amount;
}
@Override
public void attack() {
System.out.println(this.weaponName + " fired");
this.numberofbullets--;
System.out.println("Shots Left: " + this.numberofbullets);
}
@Override
public void viewDetails() {
System.out.println(this.weaponName);
}
}
In Effective Java, one of the chapters suggests that I should declare my class by the interface
. I understand the advantages, but what if I have more than one interface
?
In my main method I declare it like so:
ReloadableWeapon chargeGun = new ReloadableWeapon("ChargeGun",10);
and use it like this:
public static void reloadGameWeapon(Reloadable reload){
reload.replenish(10);
}
public static void attackGameWeapon(Weapon toAttackwith){
toAttackwith.attack();
}
If I declare it by interface
, I'll obviously only get the methods that specific interface provides. I could create another interface
called ReloadedableWeapon but what methods would be placed there? Is how I declared and used my ReloadableWeapon bad practice or code smell?
回答1:
You could create a interface that extends both Weapon
and Reloadable
.
public interface WeaponReloadable extends Weapon,Reloadable {
...
}
And having this implementation :
public final class MyWeaponReloadable implements WeaponReloadable {
...
}
In this way you could create an instance of MyReloadableWeapon
declared with the ReloadableWeapon
interface and pass it in methods with Reloadable
or Weapon
parameters :
WeaponReloadable weaponReloadable = new MyWeaponReloadable();
reloadGameWeapon(weaponReloadable);
attackGameWeapon(weaponReloadable);
回答2:
You could use generics to get a type intersection:
public static <W extends Weapon & Reloadable> doSomething(W weapon){
weapon.replenish(10);
weapon.attack();
}
Usually, it is easier to just create an "intersection interface"
interface ReloadableWeapon extends Weapon, Reloadable {}
but the generics approach works even with classes whose type hierarchy you cannot modify to include that new interface (i.e. third-party code).
来源:https://stackoverflow.com/questions/43820751/interfaces-classes-and-code-smell