-1

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.

BertSa
  • 3
  • 5
  • 2
    What's the purpose of the `License` class? Driver's licenses? You could abstract `Age` to be a compositional class that represents the features you're wanting – Rogue Feb 24 '21 at 03:40
  • To resume it's a "covidfree" pass, if you have a covid negative test its valid temporary and if you received two vaccine you have a license that does not expire. – BertSa Feb 24 '21 at 03:45
  • And yes I though of that but it makes me create empty classes and if I can avoid that it would be great. – BertSa Feb 24 '21 at 03:47
  • @KidusTekeste It's not really clear, you propose a variable plus both an extends for child? – BertSa Feb 24 '21 at 04:04
  • Until now @Rogue have the cleanest solution – BertSa Feb 24 '21 at 04:10
  • Given your example, I'd provide `License` with the method `isExpired`, which defaults to `false` for the `B` class. The `A` class could check against the expiration date. For creational design patterns, look into factory or builder (you can do conditional build logic in a builder class). – Rogue Feb 24 '21 at 04:22
  • @Rogue is it better to put `isExpired` directly in the sub class `B` instead? Because `A` never could be expired. – BertSa Feb 24 '21 at 04:26
  • `B` might never expire, but `License` doesn't necessarily have to know that. You can simply provide for the functionality and then disallow it or default it later (something you see in the decorator pattern a lot) – Rogue Feb 24 '21 at 04:27
  • @Rogue Okay makes sence I will do it that way! And the use of a builder is it a good idea if in the future I want to make a springboot entity? – BertSa Feb 24 '21 at 04:32
  • The builder is moreso just for making getting a new license instance easier. You can set the paremeters one-by-one, then `#build` into the specific subsclass of license based on the inputs – Rogue Feb 24 '21 at 04:34
  • @Rogue how will it fix the problem with `Child` ? Sorry I've never really used builders before. – BertSa Feb 24 '21 at 04:42
  • Factorize it. You want different classes of `User`, rather than all the user flavours reflected in the `Licence` hierarchy. Or use Generics: `public abstract class License extends User>`. – user207421 Feb 24 '21 at 05:11
  • @user207421 Oh that could work! But what is the best way to do it if I want the tutor to be in a variable the License? – BertSa Feb 24 '21 at 05:24
  • @user207421 I think I have found the solution – BertSa Feb 24 '21 at 05:45

3 Answers3

2

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.

Neha Jha
  • 291
  • 2
  • 9
0

Okay so I found a solution. So first I extended User to all of the age categories and then I made an interface for YoungAdult, Adult and Senior named ITutorable:

public interface ITutorable {
}

Example of implements ITutorable:

public class Adult extends User implements ITutorable{
}

And in License I made two constructors. One for just a User ITutorable and the other a Child and a ITutorable like that:

public abstract class License {

    public License(ITutorable user) {
    }

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

If you have a better idea, let me know, I would love to hear it! Otherwise thanks a lot!

BertSa
  • 3
  • 5
0

Java 8+ supports default methods in interfaces. This could supplement your interface solution as follows:

public interface LicenseBearer {

    default LicenseBearer getResponsiblePerson() { return this; }

}

This will always return the class which implements the LicenseBearer interface, unless you @Override the method, e.g. for your implementing Child class. Also, the License classes would no longer have to care, that the supplied Child has a Tutor. You could thus move the responsibility for the Child-Tutor-relationship out of the License class' domain.

You would then have an abstract class Person implements LicenseBearer from which you could derive - if necessary - your other Person-classes, of which only Child has a special behaviour regarding to Licenses:

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;
    }
}
Sorin
  • 977
  • 3
  • 12
  • It could have been a solution but like the answer from Neha Jha propose to go with a composition and I think I will go with that. Thanks for your answer! – BertSa Feb 24 '21 at 14:58