Search code examples
javaextendsclass-diagram

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


So to be short I need a class License that need to be extends into two sub classes, let's call them A and B.

License :

public abstract class License{
 
}

A :

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

B :

public class B extends Licence{
}

But both of them can also be a different type according to the age of the User (child, young Adult, Adult, Senior). I would have used an enum but in the case of the child it needs to have a tutor(User) to have a license. So the only way possible I see is to extends both 4 for every type.

Example of what I don't want:

//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{
}

The problem is not huge I just want a cleaner way to do it. :) You can explain me with code or Class diagram if its easier.


Solution

  • Inheritance: When we want to create a new class and there is already a class that includes some of the code that we want, we can derive our new class from the existing class. In doing this, we can reuse the fields and methods of the existing class.

    Composition The composition also provides code reusability but the difference here is we do not extend the class for this.

    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.

    Inheritance should only be used when subclass ‘is a’ superclass. Don’t use inheritance to get code reuse. If there is no ‘is a’ relationship, then use composition for code reuse. Classes should achieve polymorphic behavior, design flexibility, and code reuse by their composition rather than inheritance from a base or parent class.

    Example:
    Inheritance:

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

    Composition:

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

    Here the Employee class has a Person. It does not inherit from Person but instead gets the Person object passed to it, which is why it "has a" Person.

    In your case:
    Using Composition:

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

    What if Licence and A both declared 'color'? Should Documents.color return "Red" or "Blue"? Under composition this ambiguity is better handled:

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

    The Documents object is composed as an Licence and a class A. The Color behavior is taken from class Licence. This explicit composition removes ambiguity among other things and you'll encounter fewer bugs.

    General rule of thumb: Before using inheritance, consider if composition makes more sense.

    Reason: Subclassing usually means more complexity and connectedness, i.e. harder to change, maintain, and scale without making mistakes. Prefer composition over inheritance.