简体   繁体   中英

OOP - Interface inheriting an abstract class alternative

Let's say that I have an interface IMazeRoom

This interface has a function getAdjacentRooms()

Furthermore, Mazerooms have to be instanciated as IMazeRoom room1 etc.

(All of the above cannot be changed)

Let's say these classes are implementing the interface:

TrapRoom, FreeRoom, MobRoom, TreasureRoom

I want to the following functions/variables to be used in all of those subclasses

Players[] playersInRoom, setSize(), isAdditionValid(Player p)

I want to use inheritence with the three functions/variable above without modifying the interface, or duplicating the code throughout the four subclasses.

What I have tried so far

Making an abstract interface MazeRoom which implements IMazeroom, and is implemented by the four subclasses. This does not work as a constraint of this project is that the rooms have to be instantiated as IMazeroom room and doing this would lead to instantiation Mazeroom room If I wanted to use the new functions meantioned above. Also IMazeRooms cannot be modified.

Ideas

I could probably just use another interface with the functions I want to include, which would be implemented by IMazeroom, but this seems weird as this constraint should be here to teach me something, and I do not see the value in just using another interface. Furthermore, using another interface would not really cut down on code duplication, I am looking for something more like a abstract class

(The above is a completely different example from my homework task, as I want to attemp the task on my own)

Edit : Since we cannot change the interface, you can use a DefaultRoom class that implements IMazeRoom.

public class DefaultRoom implements IMazeRoom {

    protected Players[] playersInRoom;

    /* your standard method implementations */
    public boolean isAddtionValid(Player p) {
        ...
    }
}

public interface IMazeRoom {
    ...
}

Since you have to instantiate it via IMazeRoom myIMazeRoomObject = new DefaultRoom() , as long as you know which kind of Room you are handling, you can simply cast it back:

try {
    DefaultRoom myRoom = (DefaultRoom) myIMazeRoomObject;
} catch(ClassCastException ex) {
    // we didn't get a DefaultRoom object and now we have to handle that
}

Sidenote: The important thing to note is, that the interface only implements the necessary method getAdjacentRoom , as such it only constitutes information to some (arbitrary) layout that relies on getAdjacentRooms() . Your secondary constraints (immutable interface + instantiation) make it necessary to circumvent something that shouldn't happen with proper OO architecture.

You can seperate the common concrete implemetation into a abstact class and keep the interface.

Rough example based on "I am not allowed to change the interface though":

IMazeRoom:

public interface IMazeRoom {
    Set<IMazeRoom> getAdjacentRooms();
}

Common concrete implemetation:

public abstract class CommonRoom {

    private final int size;
    private final Set<Player> playersInRoom;
    private final Set<IMazeRoom> adjacentRooms;

    protected CommonRoom(int size, Set<Player> playersInRoom, Set<IMazeRoom> adjacentRooms) {
        this.size = size;
        this.playersInRoom = playersInRoom;
        this.adjacentRooms = adjacentRooms;
    }

    public int getSize() {
        return size;
    }

    public Set<Player> getPlayersInRoom() {
        return playersInRoom;
    }

    public Set<IMazeRoom> getAdjacentRooms() {
        return adjacentRooms;
    }

    public boolean isAdditionValid(Player player) {
        // Some kind of implementation returning true or false...
        return !playersInRoom.contains(player);
    }
}

TrapRoom:

public class TrapRoom extends CommonRoom implements IMazeRoom {

    public TrapRoom(int size, Set<Player> playersInRoom, Set<IMazeRoom> adjacentRooms) {
        super(size, playersInRoom, adjacentRooms);
    }
}

TreasureRoom:

public class TreasureRoom extends CommonRoom implements IMazeRoom {

    public TreasureRoom(int size, Set<Player> playersInRoom, Set<IMazeRoom> adjacentRooms) {
        super(size, playersInRoom, adjacentRooms);
    }
}

... same implementation as TreasureRoom for additional rooms.

Comment: Now all rooms are treated as IMazeRoom...

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