Where to implement methods when derived class only differs by "context" and return type
I got a base class "BaseClass" and n derived class DerivedCLass1, DerivedClass2... (I don't know if "derived" is the right term but my DerivedClassX are BaseClass with just few methods added. Like Vehicle vs Car / MotorCycle / Truc开发者_如何转开发k)
All the derived classes share a storePDF function that generates/stores a pdf. This method shouldn't be called from a BaseClass instance coz this is irrelevant. But I don't want the code to be repeating all over the derived classes. How should I organize my classes ? (or interfaces)
public class BaseClass
{
public static string select = "
select Derivedclass1DT.* from Derivedclass1DT union
select Derivedclass2DT.* from Derivedclass2DT where type='foo' union
select * from Derivedclass2DT where type='foo'
...
"
public static string objecttype= "";
public List<Baseclass> getInstance(string id)
{
/* create instance from db using the select ... */
}
public PDFObject storePDF()
{
/*
generate a pdf shouldn't be called directly from an BaseClass instance
*/
}
}
public class DerivedCLass1:BaseClass
{
public static string select = "select Derivedclass1DT.* from Derivedclass1DT";
public static string objecttype= "some text specific to this class";
public List<DerivedCLass1> getInstance(string id)
{
/* same code as is the base class just using a different select and return type */
}
/*
Don't want to store storePDF() implementation here. It is the same for each derived Class
*/
}
public class DerivedCLass2:BaseClass
{
public static string select = "select Derivedclass2DT.* from Derivedclass2DT where type='foo'";
public static string objecttype= "some other text specific to this class";
public List<DerivedCLass1> getInstance(string id)
{
/* same code as is the base class just using a different select and return type */
}
/*
Don't want to store storePDF() implementation here. It is the same for each derived Class
*/
}
you should create and abstract or virtual method storePdf in base class and in the derived classes override this method if you have some default behavior you should move it into the virtual base method if not you can create and abstract method or an Interface with this method In your case you can create a public virtual method in the base class and also make base class abstract it's avoid instantiate object of this class
The idea is to keep all the common code in base class, derive classes may override some functions if different functionality is to be achieved, there is no harm in that. You could call base method as well from derive class method if required like base.DoSomething()
from derive.DoSomething()
. Hope this help
Your List<DerivedCLass1> getInstance(string id)
function in the two derived classes don't return different types - is this correct or a typo?
In any case, because they return a type that is different to the base class they cannot override the equivalent function. Change your base class to abstract
, and try something like this:
public abstract class BaseClass //note the abstract modifier!
{
public abstract List<Baseclass> getInstance(string id);
public PDFObject storePDF()
{
/*
generate a pdf shouldn't be called directly from an BaseClass instance
*/
}
}
public class DerivedCLass1:BaseClass
{
public override List<BaseClass> getInstance(string id)
{
List<BaseClass> myList = new List<BaseClass>();
myList.Add(new DerivedClass1() { ... } ); // note the type of the class beng added!
}
/* there is no need to override storePDF(), it is already visible via this class */
}
With the storePDF()
method, leave its implementation in the base class - any consumer will have to invoke it via a derived class because the base class is abstract and cannot be created directly.
StorePdf should probably be extracted into at class of its own. Whether this should be injected into your derived classes, or StorePdf should receive them as arguments, depends on the implementation details. First, you move it away to remove the violation of SRP.
A suggestion would be to mark storePDF() as protected in the base class so that it is not accessible by anyone except the classes that inherit from it. This would prevent anyone from calling storePDF() on the base class.
Then for the child classes, you could have an abstract method in the base class that would be overriden by the base classes, which would call the protected storePDFHelper method:
public abstract class BaseClass
{
//(...)
protected PDFObject storePDFHelper() { /* Do stuff here */ }
public abstract PDFObject storePDF();
}
public class ChildClass : BaseClass, IPDFGenerator
{
public override PDFObject storePDF() { return base.storePDFHelper(); }
}
Semantically, I think this is a good option because you would: 1) not be able to call storePDF from BaseClass, which you mentioned would be good 2) be able to reuse storePDF logic over all children of BaseClass
But I'd like to hear from the other, more experienced folks too :) Hope this helps!
精彩评论