Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

method overloading and polymorphism

I'm writing a .NET web application in which administrators can customize the various data entry forms presented to their users. There are about half a dozen different field types that admins can create and customize (i.e. text, numeric, dropdown, file upload). All fields share a set of base attributes/behaviors (is the field required? Will it have a default field value?). There are also a series of field specific attributes/behaviors (i.e dropdown has a data source attribute, but text field does not). I'm leaving out many other characteristics of the problem domain for simplicity's sake.

The class hierarchy is straightforward: An abstract superclass that encapsulates common behaviors/attributes and about half a dozen concrete subclasses that deal with field specific stuff.

Each field type is rendered (i.e. mapped to) as a specific type of .NET server control, all of which derive from System.Web.UI.Control.

I created the following code to map values between the field domain objects and their corresponding UI control:

public static void Bind(Control control, IList<DocumentFieldBase> fieldBaseList)

     foreach (DocumentFieldBase fieldBase in fields){

            if (typeof (DocumentFieldText).IsInstanceOfType(fieldBase)){
                TextBox textbox = (TextBox) control;
                textbox.Text = (fieldBase as DocumentFieldText).GetValue();
            }

            if (typeof (DocumentFieldDropDown).IsInstanceOfType(fieldBase)){
                DropDown dropDown= (DropDown) control;
                dropDown.Text = (fieldBase as DocumentFieldSelectOne).GetValue().Text;
                dropDown.DataSource= (fieldBase as  DocumentFieldSelectOne).DataSource;
                dropDown.Id= (fieldBase as DocumentFieldSelectOne).GetValue().Id;
            }

            //more if statements left out for brevity
      }
}

I want to ditch those ungodly if statements that perform type checking. The approach I was shooting for was to create a method overload for each combination of field/control using subclass typing. For example:

public static void Bind(TextBox control, DocumentFieldText fieldText){
 //some implementation code
}
public static void Bind(DropDown control, DocumentFieldDropDown fieldDropDown){
 //some implementation code
}  

I was hoping that I could then rely on .NET to call the appropriate overload at runtime using the specific subclass being used: For example:

foreach (DocumentFieldBase field in fields){
  Control control = FindControl(field.Identifier);
  Bind(control, field)
}

Unfortunately, the compiler chokes when I try this: Argument '1': cannot convert from 'System.Web.UI.Control' to 'TextBox'.

If I have to cast the first argument to TextBox, I'm back to performing type checking myself and defeats the whole purpose of this exercise.

Is what I'm trying to achieve a) possible and b) a good idea?

like image 384
Mitch A Avatar asked Jul 28 '09 19:07

Mitch A


People also ask

What is the difference between polymorphism and method overriding?

Overriding is when you call a method on an object and the method in the subclass with the same signature as the one in the superclass is called. Polymorphism is where you are not sure of the objects type at runtime and the most specific method is called.

Is polymorphism overriding or overloading?

overriding is where you change the behavior of the base class via a function with the same name in a subclass. So Polymorphism is related to overriding but not really overloading.

Is method overloading and polymorphism the same in Java?

Method overloading is an implementation of compile-time polymorphism in Java. When we have one or more methods with the same name and/or return types but different parameter lists, then we say we have “overloaded” the methods.


1 Answers

The "dispatch" tag on this question is quite appropriate: what you want is called "multiple dispatch". C# (like most mainstream languages) only supports "single dispatch", where the method to be executed is selected solely on the (runtime) type of the object you call the method on, not on the (runtime) type of its arguments.

The visitor pattern can often be used to work around this. The idea is that you give DocumentFieldBase a method (that you override in concrete subclasses) which calls a method on Control (also overridden in concrete subclasses) that does the actual work.

Unfortunately, the source code of the Control class is probably not under your control*... so you'll have to resort to an even more hackish solution. The accepted answer to this question provides one that uses reflection.

*Extension methods are just syntactic sugar for static methods, and are thus resolved at compile time and of no use in this scenario.

like image 149
Thomas Avatar answered Oct 04 '22 23:10

Thomas