Polymorphism using switch statement - c#

We have some document-types:
class Document
{
public void virtual Print()
}
class PDF : Document
{
public void override Print()
{
Console.WriteLine("PDF Printed");
}
}
class Excel : Document
{
public void override Print()
{
Console.WriteLine("Excel Printed");
}
}
Suppose we have a list of documents (Document objects) and we call the virtual function Print() on all of them.
foreach(Document doc in DocumentsList)
{
doc.Print();
}
I know Polymorphism is much sophisticated way of implementing it but can we really do the same using switch statement as well? I had a long argument with a fellow on it and he says it's possible. Is it?

Yes, you can always use a switch (or an if-else chain), asking for the type. You can keep document type information in your object, for example as an enum, and use it in a switch.
Why you shouldn't do that? Because you have to extend all these switches when you add a new derived type.
To avoid that, you can implement something more automatic: Have a list of pointers to functions (or delegates in C#) which you fill for each single object with the functions suitable for this particular object (for example, the print delegate would point to print_pdf() for PDF files and to print_excel() for excel files). And hey, there you have hand-crafted a poor man's polymorphism.
The sweet thing about polymorphism is that the code using a polymorphic object can be type agnostic. It does not know what precise type the object actually has, and does not want to know. The precise type may not have existed back when the code handling the object was written. All the detail information is hidden within the type which is awesome for maintenance.

Yes you can, of course you can interrogate the member of the list on each iteration, and there are plenty of techniques that can achieve this (e.g attributes, internal Type field etc).
In fact everything you do in C# you can also do in Assembler!
However I can hardly see any benefit of avoiding the advantages of OOP.

Its a bit of a funny question, because the example using the switch is usually used to demonstrate how you usually dont want to do it.
Instead of using inheritance, you could have your document class like this:
class Doc {
public:
enum DocType{PDF,EXCEL}
private:
DocType docType;
}
And then you simply use
switch (doc.getDocType()){
...etc...
}
However, there are several reasons why usually it is nicer to use inheritance. Imagine for example, you want to add another document type. Then not only you have to add another enum field, but (and here comes the big problem) you also would have to change every single switch statement in all code that is using your Document class. That is annoying and usually you do not want to do this.

Polymorphism is the way to go for this. If you choose switch statement, you would need to use Reflection or is keyword to figure out which object's Print() you want to invoke.

Related

Is there a design pattern to handle when code depends on the subtype of two objects

I'll try to be as explicit as possible, in case there is a better solution for my problem than answering my question.
I'm working in C#.
I have a report template that can include any number of 'features' turned on. A feature might be a table of information, a pie/bar chart, a list, etc. I am generating the report as a text file, or a PDF (possibly other options in the future).
So far I have an IFeature interface, and some feature types implementing it: ChartFeature, ListFeature, etc.
I read the list of features enabled from the database and pass each one to a method along with the data id and the method returns a populated IFeature of the proper type.
I also have an IReportWriter interface that TextReportWriter and PdfReportWriter implement. That interface has a method: AddFeature(IFeature).
The problem is that AddFeature in each writer ends up looking like:
public void AddFeature(IFeature)
{
InsertSectionBreakIfNeeded();
if(IFeature is TableFeature)
{
TableFeature tf = (TableFeature)feature;
streamWriter.WriteLine(tf.Title);
for(int row=0; row < tf.Data.First.Length; row++)
{
for(int column=0; i < tf.Data.Length; i++)
{
if(i != 0)
{
streamWriter.Write("|");
}
streamWriter.Write(feature.Data[column][row]);
}
}
}
else if(IFeature is ListFeature)
{
ListFeature lf = (ListFeature)feature;
streamWriter.Write(lf.Title + ": ");
bool first = true;
foreach(var v in lf.Data)
{
if(!first)
{
streamWriter.Write(", ");
}
else
{
first = false;
}
streamWriter.Write(v);
}
}
...
else
{
throw new NotImplementedException();
}
sectionBreakNeeded = true;
}
In the PDF writer the above would be modified to generate PDF table cells, text boxes, and so forth.
This feels ugly. I like it somewhat better as AddFeature(ListFeature){...}, AddFeature(ChartFeature) because at least then it's compile time checked, but in practice it just moves the problem so now outside if the IReportWriter I'm calling if(feature is ...).
Moving the display code into the feature just reverses the problem because it would need to know whether it should be writing plain text or a PDF.
Any suggestions, or am I best just using what I have and ignoring my feelings?
Edit:
Filled in some of the conditions to give people a better idea of what is happening. Don't worry too much about the exact code in those examples, I just wrote it off the top of my head.
The general case of your problem is called double-dispatch - you need to dispatch to a method based on the runtime type of two parameters, not just one (the "this" pointer).
One standard pattern to deal with this is called the Visitor pattern. It's description traces back to the original Design Patterns book, so there's lots of example and analysis of it out there.
The basic idea is that you have two general things - you have the Elements (which are the things that you're processing) and Visitors, which process over the Elements. You need to do dynamic dispatch over both of them - so the actual method called varies depending on both the concrete type of the element and of the visitor.
In C#, and kinda sorta following your example, you'd define an IFeatureVisitor interface like this:
public interface IFeatureVisitor {
void Visit(ChartFeature feature);
void Visit(ListFeature feature);
// ... etc one per type of feature
}
Then, in your IFeature interface, add an "Accept" method.
public interface IFeature {
public void Accept(IFeatureVisitor visitor);
}
Your feature implementations would implement the Accept method like so:
public class ChartFeature : IFeature {
public void Accept(IFeatureVisitor visitor) {
visitor.Visit(this);
}
}
And then your report writers would implement the IVisitor interface and do whatever it's supposed to do in each type.
To use this, it's look something like this:
var writer = new HtmlReportWriter();
foreach(IFeature feature in document) {
feature.Accept(writer);
}
writer.FinishUp();
The way this works is that the first virtual call to Accept resolves back to the concrete type of the feature. The call to the Visit method is NOT virtual - the call to visitor.Visit(this) calls the correct overload since at that point it knows the exact static type of the thing that's being visited. No casts and type safety is preserved.
This pattern is great when new visitor types get added. It's much more painful when the elements (features in your case) change - every time you add a new element, you need to update the IVisitor interface and all the implementations. So consider carefully.
As I mentioned, there's been almost 20 years since the book was published, so you can find lots of analysis and improvements on Visitor pattern out there. Helpfully this gives you enough of a start to continue your analysis.
I would structure this in a slightly different way:
I wod have a IReport object that composes all the features in the report. This object would have methods AddFeature(IFeature) and GenerateReport(IReportWriter)
I would then have IFeature implement WriteFeature(IReport, IReportWriter) and this way delegate how the Feature is actually processed to the Feature itself.
The way you've structured the code makes me think that there is no way to write a Feature in a format agnostic way that can be processed by any given writer, so let the object itself deal with the issue.
I suppose you're trying to draw something (i.e. output it to pdf or text or whatever ...).
My guess would be to go with something like this:
interface IReportWriter {
void AddFeature(IFeature feature);
// Some other method to generate the output.
IOutput Render();
// Drawing primitives that every report writer implements
void PrintChar(char c);
void DrawLine(Point begin, Point end);
...
}
// Default implementation for ReportWriters
abstract class AbstractReportWriter {
private IList<IFeature> features = new List<IFeature>();
...
public void AddFeature(IFeature feature) {
this.features.Add(feature);
}
public IOutput Render() {
foreach(var feature in this.features) {
feature.RenderOn(this);
}
}
// Leave the primitives abstract
public abstract void PrintChar(char c);
public abstract void DrawLine(Point begin, Point end);
}
And on the feature side:
interface IFeature {
void RenderOn(IReportWriter);
}
And here is an example implementation of ChartFeature:
public class ChartFeature : IFeature {
...
public void RenderOn(IReportWriter report) {
// Draw the chart based on the primitives.
report.DrawLine(..., ...);
...
}
}
I'd avoid Visitor for two reasons: 1) it's complicated and 2) it seems your IFeature and IReportWriter hierarchies are both open to extension. Visitor is only good if the visited Element hierarchy is stable. See #Will's comment in https://stackoverflow.com/a/32256469/1168342. Simple is also a good design.
Here's what your code looks like in a UML class diagram:
AddFeature seems to be an inconsistent name. What this method is doing is formatting output, so I'd name it appropriately.
If you follow the Replace conditional with polymorphism refactoring, you can add an IFeature.WriteOutput() method that each concrete Feature will implement. Then your call in IReportWriter looks like
public void AddFeature(IFeature feature)
{
InsertSectionBreakIfNeeded();
feature.WriteOutput();
sectionBreakNeeded = true;
}
In a sense, you've applied only the Strategy pattern to your code, where IFeature plays the role of Strategy and IReportWriter plays the role of Context:
Edit for Abstract Factory
It's looking less simple, but your example code didn't really consider all the permutations of [PDF, Text] and [Chart, List].
I suggest the Abstract classes/interfaces of PdfReportFeature and ListReportFeature in case there are some functions like creating a format preamble that would be there. You could possibly apply the Template Method pattern, if needed.
The idea is that each concrete class, e.g., PdfListFeature, will have its own WriteOutput method that does what it needs to do. The concrete ReportWriter just calls feature.WriteOutput() for whatever feature is injected (aggregated) into the report.
There's no double-dispatch since you won't be mixing PDF and Text reports together (Visitor really doesn't make sense to me). When you create a report, it's one or the other type. Your Abstract Factory pattern will help you create and pass the proper class for chart or list into the writer.
I updated the Strategy part above to be consistent with the Abstract Factory approach. I hope this makes sense.

Understanding Interfaces in OOP

I am trying to learn OOP concept at an advance level. I was reading through the topic interfaces and have a confusion. But first, let me show you what exactly caused this confusion.
I tested this Code Sample. but I am confused with the use of interfaces. After implementing that code, it seems to me that I can call the method DoFirst from class A by simply creating an instance of it. so why use an interface at first place?
Something like this:
A myA = new A();
myA.DoFirst();
and similiarly,
B myB = new B();
myB.DoFirst();
In both the classes, i have to implement a method called 'DoFirst', so what good does interface provided to me?
Can't I just write these methods in different classes myself?
my Second question, say I have an interface that has 5 methods. If a class implements it, and only wants to provide implementation of 3 methods instead of writing code of all 5 methods supplied by the interface. Isn't this useless? why have access methods that i don't want?
can somebody answer these with example (Highly appreciated) please?
The advantage was already pointed out in the link you provided...
Basically you can also write
void DoSomething(IMyInterface obj)
{
obj.DoFirst();
}
And then send any type of object which implements that interface as a parameter.
A myA = new A();
DoSomething(myA);
B myB = new B();
DoSomething(myB);
The method DoSomethig doesn't care about the object's type, as long as it exposes an interface called IMyInterface.
Some Real Life examples - also, another way/reason to use interfaces.
In my own code I have an Engine which processes code to produce reports in Excel. In this engine, i had to write the code two different ways, one using the Microsoft Excel Interop, the other using the Open Office Interop. Rather than duplicate my entire engine to work two different ways, or write a lot of if statements in all the actual interop functions, I implemented an interface. Then I declared two classes, each one implementing the interface, but one uses Excel and the other uses open office. Then, in my code, I simple reference the interface and its functions and use a single if statement at the very beginning of the function to tell the interface which class to implement.
public class ExcelEngineInterop : ISSinterface
{ ... }
public class OOEngineInterop : ISSinterface
{ ... }
//cant use two variables with the same name, so use 1 interface reference instead
ISSinterface ssInt;
if(ExcelFlag)
ssInt = new ExcelEngineInterop();
else
ssInt = new OOEngineInterop();
//two VERY different functions between Excel and OpenOffice.
ssInt.OpenApp();
ssInt.OpenFile(fileName);
//etc etc and so on
This is the other reason to use an interface. When you need one block of code to act two (or more) different ways depending on some external flag.
Another Example.
There is a top level form with lots of custom user controls under it. The user fires a form level event, like a button click, but depending on which user controls are active and what settings are on them at the time the click happens, the controls themselves need to do something different. Rather than writing what could be a rediculously large number of if statements to make sure each one acts correctly from the top level, just implement an interface on each control, then do something like this:
public ButtonClick(object sender, EventArgs e)
{
//note: I dont know which of my classes currentrightcontrol belongs to at the moment.
// it could be any one of 22 different controls. It must be cast to something
// in order to call the ButtonClick method (its actual type is generic "UserControl"
IMyRunControl ctrl = CurrentRightControl as IMyRunControl;
ctrl.FormButtonClicked();
}
C# is a statically typed language (at least unless you explicitly tell it not to be). This means that the compiler uses the type of the variable to know whether the referenced object has the members you are about to use.
The interface, therefore, provides a contract to the compiler (and to other programmers, too) that this class implements that interface. Because interfaces can be shared across classes that don't have a hierarchical relationship, this means that you can define a method that can take an object as an argument by defining that interface in the parameter type.

What is the name of this bad practice / anti-pattern?

I'm trying to explain to my team why this is bad practice, and am looking for an anti-pattern reference to help in my explanation. This is a very large enterprise app, so here's a simple example to illustrate what was implemented:
public void ControlStuff()
{
var listOfThings = LoadThings();
var listOfThingsThatSupportX = new string[] {"ThingA","ThingB", "ThingC"};
foreach (var thing in listOfThings)
{
if(listOfThingsThatSupportX.Contains(thing.Name))
{
DoSomething();
}
}
}
I'm suggesting that we add a property to the 'Things' base class to tell us if it supports X, since the Thing subclass will need to implement the functionality in question. Something like this:
public void ControlStuff()
{
var listOfThings = LoadThings();
foreach (var thing in listOfThings)
{
if (thing.SupportsX)
{
DoSomething();
}
}
}
class ThingBase
{
public virtual bool SupportsX { get { return false; } }
}
class ThingA : ThingBase
{
public override bool SupportsX { get { return true; } }
}
class ThingB : ThingBase
{
}
So, it's pretty obvious why the first approach is bad practice, but what's this called? Also, is there a pattern better suited to this problem than the one I'm suggesting?
Normally a better approach (IMHO) would be to use interfaces instead of inheritance
then it is just a matter of checking whether the object has implemented the interface or not.
I think the anti-pattern name is hard-coding :)
Whether there should be a ThingBase.supportsX depends at least somewhat on what X is. In rare cases that knowledge might be in ControlStuff() only.
More usually though, X might be one of set of things in which case ThingBase might need to expose its capabilities using ThingBase.supports(ThingBaseProperty) or some such.
IMO the fundamental design principle at play here is encapsulation. In your proposed solution you have encapsulated the logic inside of the Thing class, where as in the original code the logic leaks out into the callers.
It also violates the Open-Closed principle, since if you want to add new subclasses that support X you now need to go and modify anywhere that contains that hard-coded list. With your solution you just add the new class, override the method and you're done.
Don't know about a name (doubt such exists) but think of each "Thing" as a car - some cars have Cruise Control system and others do not have.
Now you have fleet of cars you manage and want to know which have cruise control.
Using the first approach is like finding list of all car models which have cruise control, then go car by car and search for each in that list - if there it means the car has cruise control, otherwise it doesn't have. Cumbersome, right?
Using the second approach means that each car that has cruise control come with a sticker saying "I has cruise control" and you just have to look for that sticker, without relying on external source to bring you information.
Not very technical explanation, but simple and to the point.
There is a perfectly reasonable situation where this coding practice makes sense. It might not be an issue of which things actually support X (where of course an interface on each thing would be better), but rather which things that support X are ones that you want to enable. The label for what you see is then simply configuration, presently hard-coded, and the improvement on this is to move it eventually to a configuration file or otherwise. Before you persuade your team to change it I would check this is not the intention of the code you have paraphrased.
The Writing Too Much Code Anti-Pattern. It makes it harder to read and understand.
As has been pointed out already it would be better to use an interface.
Basically the programmers are not taking advantage of Object-Oriented Principles and instead doing things using procedural code. Every time we reach for the 'if' statement we should ask ourselves if we shouldn't be using an OO concept instead of writing more procedural code.
It is just a bad code, it does not have a name for it (it doesn't even have an OO design). But the argument could be that the first code does not fallow Open Close Principle. What happens when list of supported things change? You have to rewrite the method you're using.
But the same thing happens when you use the second code snippet. Lets say the supporting rule changes, you'd have to go to the each of the methods and rewrite them. I'd suggest you to have an abstract Support Class and pass different support rules when they change.
I don't think it has a name but maybe check the master list at http://en.wikipedia.org/wiki/Anti-pattern knows? http://en.wikipedia.org/wiki/Hard_code probably looks the closer.
I think that your example probably doesn't have a name - whereas your proposed solution does it is called Composite.
http://www.dofactory.com/Patterns/PatternComposite.aspx
Since you don't show what the code really is for it's hard to give you a robust sulotion. Here is one that doesn't use any if clauses at all.
// invoked to map different kinds of items to different features
public void BootStrap
{
featureService.Register(typeof(MyItem), new CustomFeature());
}
// your code without any ifs.
public void ControlStuff()
{
var listOfThings = LoadThings();
foreach (var thing in listOfThings)
{
thing.InvokeFeatures();
}
}
// your object
interface IItem
{
public ICollection<IFeature> Features {get;set;}
public void InvokeFeatues()
{
foreach (var feature in Features)
feature.Invoke(this);
}
}
// a feature that can be invoked on an item
interface IFeature
{
void Invoke(IItem container);
}
// the "glue"
public class FeatureService
{
void Register(Type itemType, IFeature feature)
{
_features.Add(itemType, feature);
}
void ApplyFeatures<T>(T item) where T : IItem
{
item.Features = _features.FindFor(typof(T));
}
}
I would call it a Failure to Encapsulate. It's a made up term, but it is real and seen quite often
A lot of people forget that encasulation is not just the hiding of data withing an object, it is also the hiding of behavior within that object, or more specifically, the hiding of how the behavior of an object is implemented.
By having an external DoSomething(), which is required for the correct program operation, you create a lot of issues. You cannot reasonably use inheritence in your list of things. If you change the signature of the "thing", in this case the string, the behavior doesn't follow. You need to modify this external class to add it's behaviour (invoking DoSomething() back to the derived thing.
I would offer the "improved" solution, which is to have a list of Thing objects, with a method that implements DoSomething(), which acts as a NOOP for the things that do nothing. This localizes the behavior of the thing within itself, and the maintenance of a special matching list becomes unnecessary.
If it were one string, I might call it a "magic string". In this case, I would consider "magic string array".
I don't know if there is a 'pattern' for writing code that is not maintainable or reusable. Why can't you just give them the reason?
In order to me the best is to explain that in term of computational complexity. Draw two chart showing the number of operation required in term of count(listOfThingsThatSupportX ) and count(listOfThings ) and compare with the solution you propose.
Instead of using interfaces, you could use attributes. They would probably describe that the object should be 'tagged' as this sort of object, even if tagging it as such doesn't introduce any additional functionality. I.e. an object being described as 'Thing A' doesn't mean that all 'Thing A's have a specific interface, it's just important that they are a 'Thing A'. That seems like the job of attributes more than interfaces.

'TypeDescriptor' for Methods - Does it exist?

I am wondering if there exists a built in class which provides a functionality similar to that of TypeDescriptor, except for method reflection rather than property.
I require this to dynamically create a context menu based on flagged methods within an object
e.g.
[ContextMenuItem(true)]
[DisplayName("Do Something")]
public override void DoSomthing()
{
...
}
I'm starting to build one myself as I haven't found one anywhere, but it always pays to ask :)
You could use the DescriptionAttribute and always look a for a particular string?
[Description("SPECIAL")]
void Doit(){}
But it's pretty easy to create your attribute type and then reflect for it, this way you can type your own parameters on to it.

Hiding a function

I have a class holding complex scientific computations. It is set up to only allow a user to create a properly instantiated case. To properly test the code, however, requires setting internal state variables directly, since the reference documents supply this data in their test cases. Done improperly, however, it can invalidate the state.
So I must have the ability, a member function, to set internal variables from the unit test programs. But I want to strongly discourage normal users from calling this function. (Yes, a determined user can muck with anything... but I don't want to advertise that there is a way to do something wrong.)
It would be nice to be able to tell Intellisense to not show the function, for instance.
The best solution I have at the moment is to just name the function something like: DangerousSet().
What other options do I have?
Follow-Up
I found Amy B's answer most useful to my situation. Thanks!
Mufasa's suggestion to use reflection was great, but harder to implement (for me).
Chris' suggestion of using a decorator was good, but didn't pan out.
BFree's suggestion on XML is also good, and was already in use, but doesn't really solve the problem.
Finally, BillTheLizard's suggestion that the problem is in the source documents is not something I can control. International experts publish highly technical books and journal articles for use by their community. The fact that they don't address my particular needs is a fact of life. There simply are no alternative documents.
You can use InternalsVisibleToAttribute to mark internal members as visible to your test assembly. It seems to shine when used in this context, though its not quite "friend".
Mark your DangerousSet function internal instead of public.
In Properties\AssemblyInfo.cs of the project containing DangerousSet:
[assembly:InternalsVisibleTo("YourTestAssembly")]
If you have two test assemblies for whatever reason, the syntax is:
[assembly:InternalsVisibleTo("TestAssembly1"),
InternalsVisibleTo("TestAssembly2")]
Decorate your method with this attribute:
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
This will hide it from Intellisense.
EDIT:
But apparently this has a rather significant caveat: "In Visual C#, EditorBrowsableAttribute does not suppress members from a class in the same assembly." Via MSDN.
Suppose you want to test this object by manipulating its fields.
public class ComplexCalculation
{
protected int favoriteNumber;
public int FavoriteNumber
{
get { return favoriteNumber; }
}
}
Place this object in your test assembly/namespace:
public class ComplexCalculationTest : ComplexCalculation
{
public void SetFavoriteNumber(int newFavoriteNumber)
{
this.favoriteNumber = newFavoriteNumber;
}
}
And write your test:
public void Test()
{
ComplexCalculationTest myTestObject = new ComplexCalculationTest();
myTestObject.SetFavoriteNumber(3);
ComplexCalculation myObject = myTestObject;
if (myObject.FavoriteNumber == 3)
Console.WriteLine("Win!");
}
PS: I know you said internal, but I don't think you meant internal.
It sounds like your real problem is in your reference documents. You shouldn't test cases that are impossible to encounter under proper use of your class. If users shouldn't be allowed to change the state of those variables, then neither should your tests.
You can also use reflection. Google search turned up Unit testing private methods using reflection.
Can your test code include a subclass of the calculations class? If so, you can mark the function protected and only inheritors will be able to use it. I'm pretty sure this also takes it out of intellisense, but I could be wrong about that.
What I've done in the past is I put XML Comments by the method and used the section to write in big bold letters. DON'T USE THIS METHOD or whatever. That way, if someone tried to use it, Intellisense would give them a nice warning.

Categories