Interfaces, Classes and Code Smell

时光怂恿深爱的人放手 提交于 2020-01-15 03:08:45

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!