简体   繁体   中英

Returning an extended class

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.

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

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);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM