有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

继承抽象类替代方案的java OOP接口

假设我有一个接口IMazeRoom

此接口有一个函数getAdjacentRooms()

此外,mazeroom必须实例化为IMazeRoom room1

(以上所有内容均无法更改)

假设这些类正在实现接口:

TrapRoom, FreeRoom, MobRoom, TreasureRoom

我希望在所有这些子类中使用以下函数/变量

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

我希望对上述三个函数/变量使用继承,而不修改接口,也不在四个子类中复制代码

到目前为止我所尝试的

制作一个抽象接口,实现IMazeroom,由四个子类实现。这不起作用,因为该项目的一个约束条件是房间必须实例化为IMazeroom room,如果我想使用上面提到的新函数,那么这样做将导致实例化Mazeroom room。此外,无法修改IMAZeroOM

想法

我可能只需要使用另一个接口来实现我想要包含的函数,这将由IMazeroom实现,但这似乎很奇怪,因为这个约束应该在这里教我一些东西,我看不到仅仅使用另一个接口的价值。此外,使用另一个接口并不能真正减少代码重复,我正在寻找更像抽象类的东西

(上面的例子与我的家庭作业任务完全不同,因为我想自己安排任务)


共 (2) 个答案

  1. # 1 楼答案

    您可以将常见的具体实现分离为Abstract类并保留接口

    基于“我不允许更改界面”的粗略示例:

    IMazeRoom:

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

    普通混凝土浇筑:

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

    财务室:

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

    。。。对于额外的房间,执行与财务室相同的操作

    评论:现在所有房间都被视为IMazeRoom

  2. # 2 楼答案

    Edit:由于我们无法更改接口,因此可以使用实现IMazeRoom的DefaultRoom

    public class DefaultRoom implements IMazeRoom {
    
        protected Players[] playersInRoom;
    
        /* your standard method implementations */
        public boolean isAddtionValid(Player p) {
            ...
        }
    }
    
    public interface IMazeRoom {
        ...
    }
    

    由于您必须通过IMazeRoom myIMazeRoomObject = new DefaultRoom()对其进行实例化,只要您知道您正在处理哪种类型的房间,就可以简单地将其回滚:

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

    旁注:需要注意的重要一点是,接口只实现必要的方法getAdjacentRoom,因此它只构成依赖于getAdjacentRooms()的某些(任意)布局的信息。 您的次要约束(不可变的接口+实例化)使得有必要绕过适当的OO体系结构不应该发生的事情