错误的方法或错误的OOP设计?

时间:2016-04-18 20:31:03

标签: oop java-8

以下是我的代码隔离。

  

可伸缩界面。

public interface Interactable <E extends Interactable> {

    List<Person> personsInteracting = new ArrayList<>();
    List<Person> personsWaiting     = new ArrayList<>();

    long INTERACTION_TIME = 5 * 60;

    default int getNumberOfPeopleInteracting () {
        return personsInteracting.size();
    }

    default int getNumberOfPeopleWaiting () {
        return personsWaiting.size();
    }

    boolean isMultipleActionsAllowed ();

    boolean isFurtherActionsAllowed ();

    public abstract boolean tryOccupiedBy (final Person person, final Interactions interaction)
        throws InteractionNotPossibleException;

    E getObject ();

    EnumSet<Interactions> getInteractions ();
}
  

InteractiveObject抽象类

public abstract class InteractiveObject implements Interactable {

    protected final String       name;
    protected       int          numberOfSimultaneousInteractions;
    protected       Interactions currentInteraction;

    public InteractiveObject (final String name) {
        this.name = name;
    }

    @Override
    public boolean isMultipleActionsAllowed () {
        return numberOfSimultaneousInteractions > 1;
    }

    @Override
    public boolean isFurtherActionsAllowed () {
        return personsInteracting.isEmpty() ||
               (getNumberOfPeopleInteracting() > numberOfSimultaneousInteractions);
    }

    @Override
    public boolean tryOccupiedBy (final Person person, final Interactions interaction)
        throws InteractionNotPossibleException {
        boolean isOccupied = false;
        if (!isFurtherActionsAllowed()) {
            throw new InteractionNotPossibleException(this + " is already in use by some other " +
                                                      "person.");
        }
        personsInteracting.add(person);
        currentInteraction = interaction;
        return isOccupied;
    }

    @Override
    public String toString () {
        return name;
    }

    public int getNumberOfSimultaneousInteractions () {
        return numberOfSimultaneousInteractions;
    }
}
  

主席(其中一个儿童班)

public class Chair extends InteractiveObject {

    private final EnumSet<Interactions> INTERACTIONS = EnumSet.copyOf(Arrays.asList(
        new Interactions[] {Interactions.DRAG, Interactions.SIT}));

    public Chair (final String objectName) {
        super(objectName);
        super.numberOfSimultaneousInteractions = 1;
    }

    @Override
    public Interactable getObject () {
        return this;
    }

    @Override
    public EnumSet<Interactions> getInteractions () {
        return INTERACTIONS;
    }
}

以下是执行并带来问题的代码段,需要提出此问题。

        final InteractiveObject chair1  = new Chair("Chair1");
        final Person            person1 = new Person("Person1");
        final Room              room    = new Room("Room1", 2, 2);
        room.personEnters(person1);
        room.putObject(chair1);
        person1.tryOccupying(chair1);

上面一段代码,成功占据了主席对象。现在,

        final InteractiveObject chair2  = new Chair("Chair2");
        final Person            person2 = new Person("Person2");
        final Room              room2    = new Room("Room2", 2, 2);
        room2.personEnters(person2);
        room2.putObject(chair2);
        person2.tryOccupying(chair2);

这段代码不允许person2占用,因为我的代码声明1个人已经与chair2进行交互,因为没有人与之交互。

  

解决我的问题:

我将personInteracting的列表移至InteractiveObject并将tryOccupiedBy函数移至每个子类,一切正常。

  

问题:

  1. 我将personsInteracting放在Interactable界面中,因为我相信Interactable的每个未来实现都会拥有它。开发人员不必自己实现。 (但也许这个想法似乎是错误的)

  2. 如果tryOccupiedBy函数具有相同的实现,那么整个OOP的目的是什么?

  3. 我现在知道隔离是错误的,我知道在哪里放置碎片以获得结果。但有人可以指出一些我不理解的OOP概念,应该以更好的方式实施吗?

1 个答案:

答案 0 :(得分:2)

ENV['RAILS_ENV'] ||= test关键字未添加到Java语言中,以执行您似乎想要实现的那种事情。界面中定义的数据旨在保持不变 - 修饰符&#39; public static&#39;自动应用于界面中的任何字段定义。如果在界面中创建default方法,则它必须是无状态的,或者仅在纯静态可用状态下直接操作。默认方法可以调用其他接口方法来修改实例状态,。

通过在接口中放置default字段,您为实现该接口的每个对象创建了相同的实例,因此您的personsInteracting方法对纯粹的全局状态起作用。

因此,在Java语言中使用tryOccupying方法的目的是支持以向后兼容的方式向接口添加新方法,仅此而已。你不应该将它重用为代码重用的一般形式 - 它从来没有用于那个并且你会得到(就像你做的那样)奇怪的行为。

你没有 default放入子课程中,所以你没有 来加载重复的代码。您仍然可以在接口中声明方法签名(这通常是接口应该执行的操作),然后在抽象基类中实现公共方法。通过将数据字段放在基类中,可以将它们设置为实例字段,因此不会在对象之间共享它们。

tryOccupiedBy