Interfaces, Classes and Code Smell

2019-07-12 08:44发布

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?

2条回答
爷的心禁止访问
2楼-- · 2019-07-12 08:55

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

查看更多
We Are One
3楼-- · 2019-07-12 09:09

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);
查看更多
登录 后发表回答