Returning an extended class

亡梦爱人 提交于 2019-12-11 19:13:05

问题


I'm not sure if this will really make any sense (I've kinda confused my self ) but what I am trying to do is create a mini-game plugin and I'm trying to make it cycle between maps, I create a new class that extends BaseGame I pass in plugin instance, world name and xml file name to the super class BaseGame, The basegame class then parses the information from xml file and setup variables. I have some methods in side the class extending BaseGame because most maps have different game types so I need to do different things for different events for example on TDM I need to stop players breaking this so I want to do this in the listener

@EventHandler
public void blockDestroy(BlockBreakEvent event) {
    plugin.mapCycler.getCurrentWorld().onBreakEvent(event);
}

The problem I face is returning the current world from the MapCycler class because all map classes have different methods, I need a way to return the map classes in a generic method that can return all map classes that extend BaseGame but I still need to be able to access the methods inside the class extending BaseGame.

Please tell me if you need more clarification.

Thanks

Edit 1:

In the BaseGame class it is common methods that will be used in all the World Classes extending BaseGame for example these methods will be used in all the classes extending BaseGame

    public String getMapName() {
    return xmlFileReader.getMapName();
}


public String getMapObjective() {
    return xmlFileReader.getMapObjective();
}
    public void resetInventory(Player player) {
    player.getInventory().clear();
    player.getInventory().setArmorContents(null);
    player.setHealth(20);
    player.setFlying(false);
    player.setGameMode(GameMode.SURVIVAL);
    player.setFoodLevel(20);
}

and in the classes extending the BaseGame class It will have unique method that relate to the world for example

public void blueWin() {
    Bukkit.getServer().broadcastMessage(Messages.colorize("Blue win - nice message in update"));
    for(String player : blueTeamList) {
        Player blue = Bukkit.getServer().getPlayer(player);
        resetInventory(blue);
        Packet206SetScoreboardObjective packet = new Packet206SetScoreboardObjective(plugin.relicWorld.sb.getObjective(plugin.relicWorld.name), 1);//Create Scoreboard create packet
        sendPacket(blue, packet);
        String loc = DatabaseManager.getLastLoc("SELECT * FROM ag_users WHERE user = \'" + blue.getName() + "\'");
        blue.teleport(LocationManager.stringToLoc(loc));
        Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), "eco give " + blue.getName() + " 250");   
    }
    for(String player : redTeamList) {
        Player red = Bukkit.getServer().getPlayer(player);
        resetInventory(red);
        Packet206SetScoreboardObjective packet = new Packet206SetScoreboardObjective(plugin.relicWorld.sb.getObjective(plugin.relicWorld.name), 1);//Create Scoreboard create packet
        sendPacket(red, packet);
        String loc = DatabaseManager.getLastLoc("SELECT * FROM ag_users WHERE user = \'" + red.getName() + "\'");
        red.teleport(LocationManager.stringToLoc(loc));
        Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), "eco give " + red.getName() + " 50"); 
    }
    Bukkit.unloadWorld(getWorld(), false);
    resetAll();
}

because it's unique to the world.


回答1:


They key is that you need to define a uniform interface for your world object. Then you can call the same method (defined in the base class/interface) and through polymorphism each subclass can react differently

interface World{
    public void onBreakEvent(BlockBreakEvent e);
}

class World1 extends BaseGame implements World{
    public void onBreakEvent(BlockBreakEvent e) {
        System.out.println("Breaking from world 1")
    }
}

class World2 extends BaseGame implements World{
    public void onBreakEvent(BlockBreakEvent  e) {
        System.out.println("Breaking from world 2")
    }
}

Now when you call plugin.mapCycler.getCurrentWorld() that should return a World object, that is, it implements the World interface. Each object can react differently but because they all share the interface, they can be treated as if they were the same.

plugin.mapCycler.getCurrentWorld().onBreakEvent(event);



回答2:


I think you must define return-type as super class. Then your method can return any class deriving form this super class.

This is called as covariant return type in java. Few examples: sample1, sample2

Here is a sample code :

class A {
    int x = 1;
}

class B extends A {
    int x = 2;
}

class Base {    
    A getObject() {
        System.out.println("Base");
        return new B();
    }
}

public class CovariantReturn extends Base {

    B getObject() {
        System.out.println("CovariantReturn");
        return new B(); 
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        Base test = new CovariantReturn();
        System.out.println(test.getObject() instanceof B);
        System.out.println(test.getObject().x);
    }
}


来源:https://stackoverflow.com/questions/15816229/returning-an-extended-class

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