pzozulka
asked on
C# inheritance design: virtual or abstract
I have the below abstract class:
Now, we have a need for another child class, but this new child class does not have all the functionality yet like the AuthorizeNetGateway child class. For example, it does not yet require GetTransactionDetailsRespo nseReason functionality.
Having said that, since GetTransactionDetailsRespo nseReason is an abstract method, it requires that all child classes override it.
What would be the best design option at the moment?
Option 1:
Override GetTransactionDetailsRespo nseReason in the new child class with an empty implementation.
Option 2:
Change GetTransactionDetailsRespo nseReason method into a Virtual method (although I don't know what the side effects of this would be for the existing AuthorizeNetGateway child class)
public abstract class ProcessorGateway
{
public abstract void AuthorizeTransaction(ProcessorGatewayContext context);
public abstract string GetTransactionDetailsResponseReason(ProcessorGatewayContext context, string _transID);
public abstract ProcessorGatewayContext NewContext();
private bool _isLive;
public bool IsLive
{
get { return _isLive; }
set { _isLive = value; }
}
}
Until now, there was only one child class called AuthorizeNetGateway which was extending the above mentioned abstract class and overriding all of its methods.Now, we have a need for another child class, but this new child class does not have all the functionality yet like the AuthorizeNetGateway child class. For example, it does not yet require GetTransactionDetailsRespo
Having said that, since GetTransactionDetailsRespo
What would be the best design option at the moment?
Option 1:
Override GetTransactionDetailsRespo
Option 2:
Change GetTransactionDetailsRespo
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
If for the moment you need GetTransactionDetailsRespo nseReason only in one class, it does not belong to the base class. Move it in the class where you use it. That way it won't appear as a phantom in the other derived classes and possibly cause problems if you use one of these through a base class variable or parameter.
If later you find that you need it in all the other classes, then bring it back as an abstract in the base class.
If you find otherwise that you need it in only some of the classes, first see if it would be used through polymorphism. If not, then simply add the method in the classes that need it, without any obligation from higher up. If however you see situations that would require many of these classes to be used interchangeably at the same place, then create an interface and have all the classes that use it implement that interface.
You can inherit from only one class, but then implement many interfaces if you have special needs for only some of the classes underneath the base class.
If later you find that you need it in all the other classes, then bring it back as an abstract in the base class.
If you find otherwise that you need it in only some of the classes, first see if it would be used through polymorphism. If not, then simply add the method in the classes that need it, without any obligation from higher up. If however you see situations that would require many of these classes to be used interchangeably at the same place, then create an interface and have all the classes that use it implement that interface.
You can inherit from only one class, but then implement many interfaces if you have special needs for only some of the classes underneath the base class.
Thanks, Jacques. One of the best explanations for abstract and interface usage. It helped me a lot as well.
ASKER
I think "not yet required" might last up to a year or more. When I implemented the base class, I thought all children of it will have the ability to use the GetTransactionDetailsRespo
The reason I implemented this method as an abstract class is because the existing AuthorizeNet child class needs to use the IsLive property of the base class. It checks for this property inside the override GetTransactionDetailsRespo
Here's how IsLive is assigned, and how the GetTransactionDetailsRespo
Open in new window
From your excellent explanation, my conclusion was that the best way was to not make the GetTransactionDetailsRespo
Perhaps I should modify the above code to not use Polymorphism since it is hard-coded to only use "Authorize.Net" anyway in the calling method. And instead of using Gateway.IsLive, I can just modify the GetTransactionDetailsRespo