Reputation: 2735
Let's say I have some abstract class User
, and then subclasses Owner
and Client
. Each of the two subclasses have some specific fields, but they both inherit common fields from the User
. This is all OK, but in a specific situation I'd like to be able to wrap any instance of User
with another field. Here is the example.
User.java
public abstract class User {
private String email;
private String password;
private String name;
}
Client.java
public class Client extends User {
private String salary;
private String profit;
}
Owner.java
public class Owner extends User {
private int numberOfClients;
private double averageClientSalary;
}
Now in a specific case, I'd like to be able to wrap such instances with a login token. So no matter if it is a Client
or the Owner
instance, it should receive another field loginToken
on top of all it's fields.
The use-case would be something like this.
Client client = new Client(email, password, name, salary, profit);
String loginToken = "123abc456";
UserLogin clientLogin = new UserLogin(client);
clientLogin.setLoginToken(loginToken);
// now this should be possible
clientLogin.getEmail(); // base class field
clientLogin.getSalary(); // derived class field
clientLogin.getLoginToken(); // field from a wrapper
So this UserLogin
should be able to receive any subclass of User
as constructor argument, and remain all of it's fields, just add the extra one, ie. loginToken
.
Would something like this be possible and how?
Basically, what would the UserLogin
class look like?
Upvotes: 1
Views: 92
Reputation: 131326
For base class fields and wrapper class fields (or to be precise getters as private
fields are not accessible from subclasses) , you can add delegation methods in the wrapper UserLogin
class.
But you could not use getters of the subclass as the wrapper manipulates a User
declared variable.
public class UserLogin {
private User user;
private String token;
public UserLogin(User user, String token) {
this.user = user;
this.token = token;
}
public String getEmail() {
return user.getEmail();
}
public String getLoginToken() {
return token;
}
// not possible for derived fields
public String getSalary() {
return user.getSalary();
}
}
As workaround to do such a thing you could make UserLogin
a generic class that provides a method that returns an instance of the specific User
class.
For example :
public class UserLogin<T extends User> {
private T user;
private String token;
public UserLogin(T user, String token) {
this.user = user;
this.token = token;
}
public String getEmail() {
return user.getEmail();
}
public T getConcreteUser() {
return user;
}
public String getLoginToken() {
return token;
}
}
You can now invoke :
UserLogin<Client> clientLogin = new UserLogin<>(new Client(), "token");
clientLogin.getEmail();
clientLogin.getConcreteUser()
.getSalary();
clientLogin.getLoginToken();
Upvotes: 2