Java 让一个类成为几个超类的子类

Java 让一个类成为几个超类的子类,java,inheritance,Java,Inheritance,在我无法更改的代码中,有几个(5+)类需要扩展几个字段。有没有办法不用编写(每次需要修改时都要编辑)几乎完全相同的代码5次就可以做到这一点?那么还有比这更优雅的方式吗: class Subclass1 extends Superclass1 { private String newField; public String getNewField() { return newField; } public void setNewField

在我无法更改的代码中,有几个(5+)类需要扩展几个字段。有没有办法不用编写(每次需要修改时都要编辑)几乎完全相同的代码5次就可以做到这一点?那么还有比这更优雅的方式吗:

class Subclass1 extends Superclass1 {
    private String newField;    

    public String getNewField() {
        return newField;
    }

    public void setNewField(String newField) {
        this.newField = newField;
    }

}
class Subclass2 extends Superclass2 {
    private String newField;    

    public String getNewField() {
        return newField;
    }

    public void setNewField(String newField) {
        this.newField = newField;
    }

}
//...
我不想要多重继承,我想要5个独立的子类-只是没有重复的代码,因为所有的子类添加完全相同


我能想到的唯一替代方法是复制原始类,并让副本扩展一个可能更糟糕的超类。

您可以使用一个泛型包装类,只要它不会太繁琐而无法更改使用它的其余代码

class Wrapper<E> {

    private E obj;
    private String newField;

    public Wrapper (E obj) {
        this.obj = obj;
    }
    public E get() {
        return obj;
    }

    public String getNewField() {
        return newField;
    }
    public void setNewField(String newField) {
        this.newField = newField;
    }
}
类包装器{
私人电子商务;
私有字符串newField;
公共包装器(E obj){
this.obj=obj;
}
公共E get(){
返回obj;
}
公共字符串getNewField(){
返回newField;
}
public void setNewField(字符串newField){
this.newField=newField;
}
}

不,在Java中不能这样做。您可以使用某些其他基于JVM的语言,例如Scala(traits)。但是,如果必须使用纯java,您可以考虑以下内容:

  • 确定要添加的字段的用途(希望是单一用途)以及所需的行为
  • 创建一个包含所有字段和新方法的新类。例如:

    public class ExtraFields  // Don't use this name!
    {
        private String myExtraField1;
        private String myExtraField2;
        // etc.
    
        public void doSomethingWithExtraFields() {
            // etc.
        }
    }
    
    public class Subclass1 extends Superclass1
    {
        private ExtraFields extraFields;
    
        public MySubclass()
        {
            super();
            extraFields = new ExtraFields();
        }
    
        public void doSomethingWithExtraFields()
        {
            extraFields.doSomethingWithExtraFields();
        }
    }
    
    public class Wrapper<T>  // Don't use this name either...
    {
        private ExtraFields extraFields;
        private T myClass;
    
        public Wrapper(T myClass) {
            this.myClass = myClass;
            this.extraFields = new ExtraFields();
        }
    }
    
然后,您可以采取以下方法之一:

  • 对五个类中的每一个都进行子类化,并添加一个字段,该字段是您在上面创建的类的实例,并相应地委托行为。如果你必须在你必须通过五门课程中的一门的地方有额外的字段,你就必须使用这种方法。例如:

    public class ExtraFields  // Don't use this name!
    {
        private String myExtraField1;
        private String myExtraField2;
        // etc.
    
        public void doSomethingWithExtraFields() {
            // etc.
        }
    }
    
    public class Subclass1 extends Superclass1
    {
        private ExtraFields extraFields;
    
        public MySubclass()
        {
            super();
            extraFields = new ExtraFields();
        }
    
        public void doSomethingWithExtraFields()
        {
            extraFields.doSomethingWithExtraFields();
        }
    }
    
    public class Wrapper<T>  // Don't use this name either...
    {
        private ExtraFields extraFields;
        private T myClass;
    
        public Wrapper(T myClass) {
            this.myClass = myClass;
            this.extraFields = new ExtraFields();
        }
    }
    
  • 创建一个新的包装类,它包含上面创建的新类和这五个子类之一的实例。可以使用泛型使此类型安全。例如:

    public class ExtraFields  // Don't use this name!
    {
        private String myExtraField1;
        private String myExtraField2;
        // etc.
    
        public void doSomethingWithExtraFields() {
            // etc.
        }
    }
    
    public class Subclass1 extends Superclass1
    {
        private ExtraFields extraFields;
    
        public MySubclass()
        {
            super();
            extraFields = new ExtraFields();
        }
    
        public void doSomethingWithExtraFields()
        {
            extraFields.doSomethingWithExtraFields();
        }
    }
    
    public class Wrapper<T>  // Don't use this name either...
    {
        private ExtraFields extraFields;
        private T myClass;
    
        public Wrapper(T myClass) {
            this.myClass = myClass;
            this.extraFields = new ExtraFields();
        }
    }
    
    公共类包装器//也不要使用此名称。。。
    {
    私人外域外域;
    私人密室;
    公共包装器(T myClass){
    this.myClass=myClass;
    this.extraFields=新的extraFields();
    }
    }
    
    在第二种方法中,您不需要严格地使用
    ExtraFields
    类。但这样做通常还是一个好主意,以便封装相关功能


  • 希望有帮助

    因为不能更改基类,所以不可能消除冗余。Eric Galluzzo在一个单独的类中存储额外字段的想法是迄今为止最好的,但我不知道这在您的情况下是否可行。如果不是,则创建一个定义额外字段的
    接口
    。您仍然需要进行大量重复键入,但至少在出错时您会立即知道。

    简短回答:在Java中,这是不可能的。即使在Java8中,通过使用默认方法的接口,您也可以实现部分功能,但不是全部功能,因为接口不能有实例字段扩展,这使Seans的建议更进一步。。。您可以使用java8/interfaces/defaults进行一些恶意攻击,以避免代码重复。类似于将贴图作为常量添加到接口。映射键为“this”(以便识别不同的对象);这个值可能是另一张地图。。。允许您存储键/值对。不确定这是否有效;但也许有兴趣发现。。。但当然:这将是一个糟糕的黑客行为;如果您使用Spring,您可以尝试使用介绍:(基于AOP的mixin功能)@Nathanhughs您可以使用静态AspectJ编译获得相同的功能,而不使用Spring。(春天很酷,但你应该有正确的理由使用它)@Sean:我的意思是,如果OP有现有的基础设施,他可能会利用它。如果他能使用AspectJ,那也行。