在 Java 中减少扩展数量以尽可能减少类的最佳方法是什么?

问题描述

简而言之,我需要一个 License 类,它需要扩展为两个子类,我们称它们为 AB

许可证:

public abstract class License{
 
}

A:

public class A extends Licence{
 Date valid;
 Date expire;
}

乙:

public class B extends Licence{
}

但根据User(儿童、年轻成人、成人、老年人)的年龄,它们也可以是不同的类型。我会使用枚举,但在孩子的情况下,它需要有导师(User)才能获得许可证。 所以我看到的唯一可能的方法是为每种类型扩展 4。

我不想要的示例:

//extends of A
public class AChild extends A{
 User tutor;
}
public class AYoungAdult extends A{
}
public class AAdult extends A{
}
public class ASenior extends A{
}

//extends of B
public class BChild extends B{
 User tutor;
}
public class BYoungAdult extends B{ 
}
public class BAdult extends B{
}
public class BSenior extends B{
}

问题并不大,我只是想要一种更简洁的方法。 :) 如果更容易,你可以用代码或类图来解释我。

解决方法

继承: 当我们想要创建一个新类并且已经有一个包含我们想要的一些代码的类时,我们可以从现有类中派生出我们的新类。这样做,我们可以重用现有类的字段和方法。

组成 该组合还提供了代码可重用性,但不同之处在于我们没有为此扩展类。

继承 组成
我们定义了我们继承的类(超类),最重要的是它不能在运行时改变 我们只定义了一个我们想要使用的类型,它可以保持不同的实现,也可以在运行时改变。因此,组合比继承灵活得多。
我们只能扩展一个类,也就是说不能扩展一个以上的类,因为java不支持多重继承。 它允许使用来自不同类的功能。
继承不能扩展final类。 组合允许代码重用甚至来自最终类。
这是一种 is-a 关系。 这是一种关系。

仅当子类‘是’超类时才应使用继承。 不要使用继承来获得代码重用。如果不存在“是”关系,则使用组合进行代码重用。类应该通过组合而不是从基类或父类继承来实现多态行为、设计灵活性和代码重用。

示例:
继承:

class Person {
   String title;
   String name;
   int age;
}

class Employee extends Person {
   int salary;
   String title;
}

组成:

class Person {
   String title;
   String name;
   int age;

   public Person(String t,String n,int a) {
      this.title = t;
      this.name = n;
      this.age = a;
   }

}

class Employee {
   int salary;
   private Person person;

   public Employee(Person p,int s) {
       this.person = p;
       this.salary = s;
   }
}

这里 Employee 类有一个 Person。它不从 Person 继承,而是将 Person 对象传递给它,这就是它“拥有”Person 的原因。

就你而言:
使用合成:

import java.util.Date;
class License{
   String type;
   String name;

   public License(String t,String n) {
      this.type = t;
      this.name = n;
   }    
}

class A{
   Date valid;
   Date expire;
   private License license;

   public A(License l,Date v,Date e) {
       this.license = l;
       this.valid = v;
       this.expire = e;
   }
}

如果 License 和 A 都声明为“颜色”怎么办? Documents.color 应该返回“红色”还是“蓝色”?在组合下,这种歧义可以更好地处理:

class Documents {
    String color;

    public Documents(License li,A aa) {
        this.color = li.color;
    }
}

文档对象由一个许可证和一个类 A 组成。颜色行为取自类许可证。这种明确的组合消除了歧义,您会遇到更少的错误。

一般经验法则:在使用继承之前,请考虑组合是否更有意义。

原因:子类化通常意味着更多的复杂性和关联性,即更难在不出错的情况下进行更改、维护和扩展。更喜欢组合而不是继承。

,

好的,所以我找到了解决方案。 所以首先我将 User 扩展到所有年龄类别,然后我为 YoungAdultAdultSenior 创建了一个名为 ITutorable 的接口:

public interface ITutorable {
}

implements ITutorable 的示例:

public class Adult extends User implements ITutorable{
}

在 License 我做了两个构造函数。一个只用于 User ITutorable,另一个用于 ChildITutorable

public abstract class License {

    public License(ITutorable user) {
    }

    public License(Child user,ITutorable tutor) {
    }
}

如果您有更好的主意,请告诉我,我很乐意听到! 否则非常感谢!

,

Java 8+ 支持接口中的 default 方法。 这可以补充您的界面解决方案,如下所示:

public interface LicenseBearer {

    default LicenseBearer getResponsiblePerson() { return this; }

}

这将始终返回实现 LicenseBearer 接口的类,除非@Override该方法,例如用于实现 Child 类。此外,License 类将不再需要关心所提供的 Child 是否具有 Tutor。因此,您可以将 Child-Tutor-relationship 的责任从 License 类的域中移出。

然后,您将拥有一个 abstract class Person implements LicenseBearer,如果需要,您可以从中派生出您的其他 Person 类,其中只有 ChildLicense 具有特殊行为:

public class Child extends Person {

    Person tutor;

    private Child() { /* No Child without a tutor Person allowed */ }

    public Child(Person tutor) {
        this.tutor = tutor;
    }

    @Override
    public LicenseBearer getResponsiblePerson() {
        return this.tutor;
    }
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...