Reputation: 71
Problem: With the following classes, I am trying to select a base class at runtime depending upon an instance variable of parent class in Java. I believe there should be some fundamental property in OOPS which can help me achieve it which I am just missing.
class Transaction{
int id;
enum transactionType;
}
class ATypeTransaction extends Transaction{
/* bunch of instance variable specific to ATypeTransaction */
}
class BTypeTransaction extends Transaction{
/* bunch of instance variable specific to BTypeTransaction */
}
/* The event can be triggered with any transactionType as declared in the enum TransactionType as each event would be associated with one transaction.*/
class Event{
int eventId;
enum transactionType;
}
Based on the transactionType, I have to prepare Transaction Payload and attributes will be different for different base classes as shown below.
My Approach: I am trying to use something like this (static polymorphism within switch-case) in an attempt to resolve the Transaction instance based on the transactionType.The problem with this approach is I am still not able to get hold of the child class. Rather I am getting parent class which stops me from accessing child class attributes.
public Transaction selectTransaction(TransactionType transactionType){
Transaction transaction;
switch(transactionType) {
case = "AType":
transaction= new ATypeTransaction();
break;
case = "BType":
transaction= new BTypeTransaction();
break;
}
return transaction;
}
Please help me out with this problem and provide a good design to solve this. Thanks in advance.
Upvotes: 0
Views: 635
Reputation: 5063
If you're set on selecting type of returned object using switch and enum type I think this will be the best solution:
public static enum TransactionType {
AType,
BType
}
public static class Transaction {
public static void main(String[] args) {
ATypeTransaction transA = selectTransaction(TransactionType.AType);
BTypeTransaction transB = selectTransaction(TransactionType.BType);
Transaction trans = selectTransaction(TransactionType.AType);
transA.doA();
transB.doB();
((ATypeTransaction)trans).doA();
//The following will cause class cast exception
ATypeTransaction transC = selectTransaction(TransactionType.BType);
((BTypeTransaction)trans).doB();
}
@SuppressWarnings("Unchecked")
public static <T extends Transaction> T selectTransaction(TransactionType transactionType){
switch(transactionType) {
case AType:
return (T) new ATypeTransaction();
break;
case BType:
return (T) new BTypeTransaction();
break;
}
}
}
public static class ATypeTransaction extends Transaction {
public void doA() {}
}
public static class BTypeTransaction extends Transaction {
public void doB() {}
}
Unfortunately, unless you know if the result of selectTransaction
method will be a specific superclass of class Transaction (so you can save it to a variable of a correct type) or if you check the type using operator instanceof
(in case of variable of class Transaction
), you'll risk JVM throwing ClassCastException
.
Upvotes: 1
Reputation: 7290
For some reason, you want your API to contain a method like Transaction selectTransaction(...)
.
This assumes that your callers won't care about the concrete implementation of Transaction
, but can do everything they want just using methods from the Transaction
type, never needing anything specific from ATypeTransaction
or BTypeTransaction
.
Your question shows that this isn't true, the callers seem to need access to specific elements (methods or even fields) of the individual types.
There are two possible roads:
ATypeTransaction
and BTypeTransaction
, orUpvotes: 0
Reputation: 501
i think switch-cases in java only works with byte, short, char, string and enum. You could use the instance of Operator in an if statement. But maybe there are some better solutions when it comes to design patters.
Upvotes: 0
Reputation: 2357
put the business logic to your data:
class Transaction{
int id;
enum transactionType;
public void handleTransaction() {
//common code
}
}
class ATypeTransaction extends Transaction{
/* bunch of instance variable specific to ATypeTransaction */
@Override
public void handleTransaction() {
// access specific attributes
super.handleTransaction();
}
}
Upvotes: 0