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

What is the best way to reduce the number of extends to have as less class possible in Java?

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

许可证:

public abstract class License{
 
}

一个:

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

B :

public class B extends Licence{
}

但两者也可以根据User的年龄不同(child,young Adult,Adult,Senior)。我会使用枚举,但在 child 的情况下,它需要有导师 (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{
}

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

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

的界面
public interface ITutorable {
}

implements ITutorable的例子:

public class Adult extends User implements ITutorable{
}

在许可证中我制作了两个构造函数。一个只是 User ITutorable,另一个是 ChildITutorable,就像这样:

public abstract class License {

    public License(ITutorable user) {
    }

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

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

继承: 当我们想要创建一个新的 class 并且已经有一个包含我们想要的一些代码的 class 时,我们可以从现有的 class 派生我们的新 class .这样做,我们可以重用现有class.

的字段和方法

作文 该组合还提供了代码可重用性,但这里的区别是我们没有为此扩展 class。

Inheritance Composition
We define the class which we are inheriting(super class) and most importantly it cannot be changed at runtime We only define a type which we want to use and which can hold its different implementation also it can change at runtime. Hence, Composition is much more flexible than Inheritance.
We can only extend one class, in other words more than one class can’t be extended as java does not support multiple inheritance. It allows to use functionality from different class.
Inheritance cannot extend final class. Composition allows code reuse even from final classes.
It is an is-a relationship. It is a has-a relationship.

只有当subclass ‘是’ superclass时才应该使用继承。 不要使用继承来重用代码。如果没有“是”关系,则使用组合进行代码重用。 类 应该通过组合而不是从基类或父类继承来实现多态行为、设计灵活性和代码重用 class.

示例:
继承:

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 class 有一个 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 都声明了 'color' 怎么办? 应该 Documents.color return “红色”还是“蓝色”?在组合下,这种歧义得到了更好的处理:

class Documents {
    String color;

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

Documents 对象由许可证和 class A 组成。颜色行为取自 class 许可证。这种明确的组合消除了其他方面的歧义,您会遇到更少的错误。

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

原因: Subclassing 通常意味着更多的复杂性和关联性,即更难更改、维护和扩展而不犯错误。更喜欢组合而不是继承。

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

public interface LicenseBearer {

    default LicenseBearer getResponsiblePerson() { return this; }

}

这将始终return实现 LicenseBearer 接口的class,除非@Override方法,例如为了您的实施 Child class。此外,License classes 将不再需要关心所提供的 Child 是否具有 Tutor。因此,您可以将 Child-Tutor 关系的责任移出 License class' 域。

然后您将拥有一个 abstract class Person implements LicenseBearer,如果需要,您可以从中派生出您的其他 Person-class,其中只有 ChildLicenses:

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