【问题标题】:Workaround for inability to have multiple inheritance in Java在 Java 中无法进行多重继承的解决方法
【发布时间】:2014-05-23 15:28:45
【问题描述】:

我知道您不能在 Java 中扩展多个类。所以,我需要帮助解决这个问题。

我有这些课程:

abstract class ObjWithID {
    final int id;

    public ObjWithID(int id) {
        this.id = id;
    }
}

abstract class ObjWithIDActivity extends ObjWithID {

    public ObjWithIDActivity(int id) {
        super(id);
    }

    boolean active;

    public boolean isActive() {
        return active;
    }

    public void setActive(boolean active) {
        this.active = active;
    }
}

abstract class ObjWithIDPriority extends ObjWithID {

    public ObjWithIDPriority(int id) {
        super(id);
    }

    int priority;

    public void setPriority(int priority) {
        this.priority = priority;
    }

    public int getPriority() {
        return priority;
    }
}

我的一些课程(大部分)需要activitypriority。所以,在一个完美的世界里,我会这样写:

class Employee extends ObjWithIDPriority, ObjWithIDActivity implements Comparable<Header> {

    public Employee(int id) {
        super(id);
    }

    @Override
    public int compareTo(Header o) {
        return Integer.compare(o.priority, priority);
    }
}

当然,你不能扩展多个类。

在我当前的代码中,我只是创建了第三个类:

abstract class ObjWithIDActivityPriority extends ObjWithID {

    public ObjWithIDActivityPriority(int id) {
        super(id);
    }

    boolean active;

    public boolean isActive() {
        return active;
    }

    public void setActive(boolean active) {
        this.active = active;
    }

    int priority;

    public void setPriority(int priority) {
        this.priority = priority;
    }

    public int getPriority() {
        return priority;
    }
}

但是,这导致我不得不编写更多代码,因为如果我创建一个接受ObjectWithIDActivity 作为参数的方法,我需要为ObjWithIDActivityPrioritys 复制它。

我已经尝试过使用interfaces 的多重继承解决方法,但这会导致问题,因为我正在使用字段int idint priorityboolean active 以及这些字段的getter/setter。另外,接口不能有构造函数。

那么,实现这一点的最佳方法是什么?三等舱是唯一的选择吗??

【问题讨论】:

  • “优先组合而不是继承”。不幸的是,并非没有样板。
  • 使用 Java 8!接口的多重继承! :D
  • @DirkyJerky 在这种情况下不起作用,因为您不能拥有实例变量。
  • 既然你可以争辩说任何活动都必须有一个优先级,为什么不让 ObjWithIDActivity 扩展 ObjWithIDPriority 呢?
  • 我认为没有足够的信息来提供解决方案。此类问题的答案取决于整个应用程序的整体设计需求;您不能简单地将其简化为一个小测试用例并问“答案是什么?”。在这种情况下,我不明白为什么需要ObjectWithIDActivityObjectWithIDPriority 抽象类,而不是单独的ActivityPriority 类,它们将成为某些对象中的实例字段。它看起来像一种“设计气味”。也许有充分的理由,但我不能从一个小例子中看出。

标签: java multiple-inheritance


【解决方案1】:

我对作文的看法:

public interface IDItf {
    abstract int getId();
    abstract void setId(int id);
}
class IDSupport implements IDItf {
    int id;

    public IDSupport(int id) {
        super();
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}
public interface PriorityItf {
    abstract int getPriority();
    abstract void setPriority(int priority);
}

... (PrioritySupport class)

public interface ActivityItf {
    abstract boolean isActive();
    abstract void setActive(boolean active);
}

... (ActivitySupport class)

class Employee implements IDItf, PriorityItf, ActivityItf, Comparable<Header> {
    private IDSupport idSupport;
    private PrioritySupport prioritySupport;
    private ActivitySupport activitySupport;

    public Employee(int id) {
        super();
        idSupport = new IDSupport(id);
        prioritySupport = new PrioritySupport(0);
        activitySupport = new ActivitySupport(false);
    }

    @Override
    public int compareTo(Header o) {
        return Integer.compare(o.prioritySupport.getPriority(), prioritySupport.getPriority());
    }

    // Delegate methods (create them with Eclipse or other IDE's features)
    public int getId() {
        return idSupport.getId();
    }
    public void setId(int id) {
        idSupport.setId(id);
    }
    ...
}

...Support 类相当琐碎,但如果它们需要更多逻辑,它们会更有意义。 Employee 类中的字段可以使用 final 关键字。

我发现过去的作文很有帮助。拥有样板代码最初感觉并不好。但是,委托方法可以由 IDE 生成。 Support 类也可以主要生成(创建字段,让 IDE 创建构造函数和 getter/setter)。不利的一面可能是仍然需要维护的生成代码的大幅下滑。但是,从长远来看,我更喜欢更简单的代码,即使阅读起来很无聊。在过去的 25 年中,我不止一次地查看过一段时间前的代码,想知道我在想什么。有时,如果一个人没有记录当时很明显但现在不是的关键提示,即使是 cmets 也无济于事。

【讨论】:

    【解决方案2】:

    Java 方式是使用接口ActivablePriorisable 并将包括状态在内的实现放入所有实现类中。

    这里的Comparable应该被Priorisable继承。

    如果你真的想分解状态声明(但恕我直言,没有必要),你可以将你的模型类隐藏在某个接口后面(EmployeeEmployeeImpl 实现)并使模型实现类扩展一个暴露的modelBase POJO所有可能的属性(活动,优先级...)。当通过它们的接口操作模型类时,只会公开可用的方法。

    【讨论】:

    • 如果你想要强大且安全的多重继承,请使用 scala 特征;)(也可以在 JVM 中完美运行)
    【解决方案3】:

    不是一个可行的答案,因为提问者说他​​不能使用 Java 8,但我想我会发布这个,因为它很有趣。可以肯定的是,这令人厌恶,但乍一看,它确实绕过了 Java 的多重继承限制。有cmets吗?

    public interface ObjWithID {
        public static final Map<ObjWithID, Integer> idMap = new HashMap<>();
        default public int getId() {
            return idMap.get(this);
        }
    }
    
    
    public interface ObjWithIDActivity extends ObjWithID {
        public static final Map<ObjWithIDActivity, Boolean> activeMap = new HashMap<>();
        default public boolean isActive() {
            return activeMap.get(this);
        }
        default public void setActive(boolean active) {
            activeMap.put(this, active);
        }
    }
    
    
    public interface ObjWithIDPriority extends ObjWithID {
        public static final Map<ObjWithIDPriority, Integer> priorityMap = new HashMap<>();
        default public int getPriority() {
            return priorityMap.get(this);
        }
        default public void setPriority(int priority) {
            priorityMap.put(this, priority);
        }
    }
    
    
    public class NewClass implements ObjWithIDActivity, ObjWithIDPriority {
        public void foo() {
            int id = getId();
            int priority = getPriority();
            boolean active = isActive();
        }
    }
    

    祝你钻石图案好运!

    【讨论】:

    • 一个问题是它会破坏父接口的自动垃圾收集,因为映射包含对它们的引用。将HashMap 替换为WeakHashMap 会起作用。
    猜你喜欢
    • 2023-04-08
    • 1970-01-01
    • 2013-08-16
    • 2019-12-05
    • 1970-01-01
    • 1970-01-01
    • 2013-05-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多