Reputation: 177
I have a question about abstract classes in Java. I have created abstract class like this:
public class userClass {
private String email;
String accountType;
account account;
public userClass(String email, String accountType){
this.setEmail(email);
this.setAccountType(accountType);
if(accountType.equals("basic")){
this.account = new basicAccount();
}
else if(accountType.equals("premium")){
this.account = new premiumAccount();
}
}
As you see I have accounts of two types: basic and premium, they are both extensions of account abstract class. Now I would like to add method only to premium class, but when I'm trying to do so, I receive an error saying that I have to implement it in account class, which I don't want. Is it possible to do it in other way? To avoid putting empty method in account and basicAccount classes?
Upvotes: 0
Views: 95
Reputation: 3161
So you if you have an Account
class like:
public abstract class Account{
public abstract void doSomethingAccountLike();
//more stuff
}
You can have child classes:
public class BasicAccount extends Account{
public void doSomethingAccountLike(){
//implementation specific to basic accounts
}
}
public class PremiumAccount extends Account{
public void doSomethingAccountLike(){
//implementation specific to premium accounts
}
public void doSomethingPremiumLike(){
//something that only makes sense
// in the context of a premium account
}
}
The method doSomethingPremiumLike()
is only available when you have an instance of a PremiumAccount
i.e.:
public class AccountDemo{
public static void main(String[] args){
PremiumAccount premium = new PremiumAccount();
BasicAccount basic = new BasicAccount();
Account generalAccount = premium;
//valid- the compiler knows that the
//premium object is an instance of the
//premium class
premium.doSomethingPremiumLike();
//Would cause a compile error if uncommented.
//The compiler knows that basic is an instance
//of a BasicAccount, for which the method
//doSomethingPremiumLike() is undefined.
//basic.doSomethingPremiumLike();
//Would generate a compiler error if uncommented.
//Even though generalAccount actually refers to
//an object which is specifically a PremiumAccount,
//the compiler only knows that it has a reference to
//an Account object, it doesn't know that it's actually
//specifically a PremiumAccount. Since the method
// doSomethingPremiumLike() is not defined for a general
//Account, this won't compile
//generalAccount.doSomethingPremiumLike();
//All compile- all are instances of Account
//objects, and the method doSomethingAccountLike()
//is defined for all accounts.
basic.doSomethingAccountLike();
premium.doSomethingAccountLike();
generalAccount.doSomethingAccountLike();
}
}
Your issue
It sounds to me like your issue is likely that in the class UserClass
, you have a field Account account
. In your constructor, you assign either a new BasicAccount()
or a new PremiumAccount()
to the field account
. This is perfectly fine, but once you do that, the compiler no longer knows in any given case whether the account
field refers to a PremiumAccount
instance or a BasicInstance
. This means that if you try to call account.doSomethingPremiumLike()
, you will get a compiler error. You can get around this restriction at runtime:
In UserClass
somewhere:
if(account instanceof PremiumAccount){
//if we're sure that account is actually a PremiumAccount,
//cast it to a PremiumAccount here to let the compiler know
//that doSomethingPremiumLike() can be called
((PremiumAccount)account).doSomethingPremiumLike();
}
Note: I have changed the names of your classes to start with upper case letters as is the common convention in Java and most other OOP languages. It's good to get in the habit of following this convention to help others read your code.
Upvotes: 2