Understanding polymorphism in general (c# example) - c#

I am currently in the middle of self-teaching some basic concepts of C# and I am experimenting with abstract classes and polymorphism. I thought I got the basic concept but it turned out that the concept doesn't work like I understood it :). However - I hope I get some answers which clear the dust a little bit :).
The whole task I am trying to achieve is to extend an abstract base class and use the extension with an object of the base class. Like here:
I have an abstract class which implements an abstract property like:
public abstract class BaseClass
{
public abstract MyProperty mP{get;}
}
where the property is
public abstract class MyProperty
{
public abstract string PropertyName{get;}
}
Now I am deriving the MyProperty class for an actual implementation like
public class DerivedProperty : MyProperty
{
public override string PropertyName
{
get
{
return this._name;
}
}
private _name = "Property1";
/* some other implementation follows here...... */
}
As I've understood polymorphism and inheritance it should now be possible to instantiate a derived class from BaseClass and override the property MyProperty with an object of DerivedProperty like this:
public class DerivedClass : BaseClass
{
public override DerivedProperty mP
{
get
{
return dP;
}
}
private DerivedProperty dP = new DerivedProperty();
/* more implementation follows here...... */
}
Because DerivedProperty is an object of MyProperty and DerivedProperty at the same time it is possible to use it where either MyProperty or DerivedProperty is referenced. At least that's what I thought but it seems that this is wrong.
Now I am wondering - why is polymorphism so useful when something like above is not possible? Because even when I try something like this:
public class DerivedClass : BaseClass
{
public override MyProperty mP
{
get
{
return dP as DerivedProperty;
}
}
private DerivedProperty dP = new DerivedProperty();
/* more implementation follows here...... */
}
I still get only my base object MyProperty and not my extended object DerivedProperty which I want to get.
I know why I get those results - I just don't seem logical to me :). Is it really like polymorphism is supposed to work or is my implementation just crap and I have to do it in a different way to get my extended property?
Appreciate your help here!

You have to provide the same type for overrided property. You can use it later in your abstract BaseClass. Parameters as well as return value of member have to be the same when overriding. It is usually not a problem.
I've prepared following examples that my code look similar to yours.
In some scenarios I've seen that there is added second property with more specific type and different (more specific) name:
public abstract class BaseCar
{
public abstract BaseDriver Driver { get; }
}
public abstract class BaseDriver
{
public abstract string Name { get; set; }
}
public class AgressiveDriver : BaseDriver
{
public override string Name { get; set; }
}
public class FastCar : BaseCar
{
private AgressiveDriver _agressiveDriver = new AgressiveDriver();
public override BaseDriver Driver { get { return _agressiveDriver; } }
public AgressiveDriver AgressiveDriver { get { return _agressiveDriver; } }
}
Second approach is to use generics:
public abstract class BaseCar<TDriver>
where TDriver : BaseDriver
{
public abstract TDriver Driver { get; }
}
public abstract class BaseDriver
{
public abstract string Name { get; set; }
}
public class AgressiveDriver : BaseDriver
{
public override string Name { get; set; }
}
public class FastCar : BaseCar<AgressiveDriver>
{
private AgressiveDriver _agressiveDriver = new AgressiveDriver();
public override AgressiveDriver Driver { get { return _agressiveDriver; } }
}
but I think first approach is better because there is no problem with creating/using BaseCar objects (for example to create BaseCar<> variable you have to specify type parameter). Also it makes sense to create more specific name for more specific property.

I think you have an extra bit of complexity you don't need. You have an abstract class inside an abstract class. If you are just learning/relearning this you have skipped a couple easy steps for understanding. Here's a simpler example to start with.
public abstract class Shape
{
public abstract double GetArea();
public abstract double Circumference();
}
public class Square: Shape
{
public double width {get; set;}
public override double GetArea()
{
return width * width;
}
public override Circumference()
{
return width * 4;
}
}
You can now instantiate a Square or create a Circle Class and be able to use either where you use Shape.

Related

Accessing base class function from secondarily derived functions

I seriously hope my title is clear enough. If it's not I'm happy to have better suggestions.
The situation is thus (variable types are just examples):
public abstract class A
{
public virtual string X(string arg)
{
return "blarg";
}
}
public class CommonProperties : A
{
public string foof { get; set;} = "widget";
public string yay { get; set; }
public override string X(string arg)
{
return base.X(arg);
}
}
public class B : CommonProperties
{
public string UniqueProperty1 { get; set; }
public override string X(string arg)
{
return base.X(arg);
}
}
public class C : CommonProperties
{
public string UniqueProperty2 { get; set; }
public override string X(string arg)
{
return base.X(arg);
}
}
class D : A
{
public override string X(string arg)
{
return base.X(arg);
}
}
}
I'm generalizing my problem. This is not my actual code.
The problem is that C# does not allow multiple inheritance for abstract classes, interfaces don't allow for default code (yet) nor do they allow for default initializers.
I'd like CommonProperties to be derived from the abstract class and the classes derived from it (classes B and C) to be able to directly access the original abstract class's implementation of the X function rather than the overriding CommonProperties implementation of it. I've tried doing base.base.X(arg) but that didn't work. The next best way would be to have classes B and C derived from both class A and class CommonProperties but C# doesn't allow this. Making class A an interface won't work because I have a large number of classes derived from it and that would mean I'd have to copy the needed code into every. single. one. I can't make CommonProperties an interface because of that restriction on default values. I could move the common properties into their derived classes but that defeats code reuse (I may need to add additional properties over time and that would mean updating would be slower and more prone to error, etc.)
I can't wait until C# 8.0 (theoretically) having a default implementation of functions. If I can get B and C to directly access the hidden A.X() function that is hidden by the CommonProperties.X() function that would be a good workaround. I suspect that latter solution is possible with reflection (in fact in my project the A class is doing just that so the topic isn't difficult for me), but I'd like to know if there was a more direct method.
Edit: Adding one more class to clarify the issue better. I forgot that CommonProperties was supposed to inherit from A and also show that other classes directly inherit from A.
You need to add a non virtual method to class A that calls the A.X implementation. The method name includes the class name, I used double underscore to separate method name and class name.
public abstract class A
{
public virtual string X(string arg)
{
return "blarg";
}
public string X__A(string arg)
{
return X(arg);
}
}
public class CommonProperties : A
{
public string foof { get; set;} = "widget";
public string yay { get; set; }
public override string X(string arg)
{
return "comarg";
}
}
public class B : CommonProperties
{
public string UniqueProperty1 { get; set; }
public override string X(string arg)
{
return X__A(arg);
}
}

How to cast into generic base class

I have few classes which inherits from a generic class like FooBasePolicy<TFooTarget>. And I want to cast my derived classes by their base class (not sure if its right way to say it). My classes are:
public class FooTarget{}
public class GTeamTarget : FooTarget{}
public class MTeamTarget : FooTarget{}
public class FooBasePolicy{}
public class FooBasePolicy<TFooTarget> : FooBasePolicy where TFooTarget : FooTarget
{
public virtual TFooTarget SomeFooTarget { get;set; }
}
public class GTeamPolicy : FooBasePolicy<GTeamTarget>
{
public GTeamPolicy()
{
SomeFooTarget = new GTeamTarget();
}
}
public class MTeamPolicy : FooBasePolicy<MTeamTarget>
{
public GTeamPolicy()
{
SomeFooTarget = new MTeamTarget();
}
}
And then I tried to use these this way,
problem is I don't know upfront which TeamTarget it is. It can be G or M.
FooBasePolicy<FooTarget> policy = null;
if (something.Equals("GTEAM"))
{
//This gives me an implicit conversion error. It can't cast.
policy = FromBinary(type, funnelData.Data) as FooBasePolicy<FooTarget>;
}
else if (something.Equals("MTEAM"))
{
policy = FromBinary(type, funnelData.Data) as FooBasePolicy<FooTarget>;
}
FromBinary actually returns a deserialized object.
But it perfectly can cast into FooBasePolicy. But then I miss SomeFooTarget property.
Any idea? Please help.
As the others said, just define an interface:
public interface IFooBasePolicy<out TFooTarget> {
TFooTarget SomeFooTarget { get; }
}
The base class FooBasePolicy now looks like:
public class FooBasePolicy<TFooTarget> : IFooBasePolicy<TFooTarget>
where TFooTarget : FooTarget {
public virtual TFooTarget SomeFooTarget { get; set; }
}
Later you can use the following cast:
policy = ((IFooBasePolicy<FooTarget>)FromBinary(something));
Short explanation:
FooBasePolicy<FooTarget> is not a base class of FooBasePolicy<GTeamTarget>
this can be resolved with covariance: GTeamTarget is a subtype of FooTarget, therefore FooBasePolicy<GTeamTarget> is a subtype of FooBasePolicy<FooTarget>
but covariance is only allowed on interfaces in C#
so you need an interface with a coveriant type declaration

Generic Interface inheriting Non-Generic One C#

This is class design question.
I have main abstract class
public abstract class AbstractBlockRule
{
public long Id{get;set;}
public abstract List<IRestriction> Restrictions {get;};
}
public interface IRestriction{}
public interface IRestriction<T>:IRestriction where T:struct
{
T Limit {get;}
}
public TimeRestriction:IRestriction<TimeSpan>
{
public TimeSpan Limit{get;set;}
}
public AgeRestriction:IRestriction<int>
{
public int Limit{get;set;}
}
public class BlockRule:AbstractBlockRule
{
public virtual List<IRestriction> Restrictions {get;set;}
}
BlockRule rule=new BlockRule();
TimeRestriction t=new TimeRestriction();
AgeRestriction a=new AgeRestriction();
rule.Restrictions.Add(t);
rule.Restrictions.Add(a);
I have to use non-generic Interface IRestriction just to avoid specifying generic type T in main abstract class. I'm very new to generics. Can some one let me know how to better design this thing?
Your approach is typical (for example, IEnumerable<T> implements IEnumerable like this). If you want to provide maximum utility to consumers of your code, it would be nice to provide a non-generic accessor on the non-generic interface, then hide it in the generic implementation. For example:
public abstract class AbstractBlockRule
{
public long Id{get;set;}
public abstract List<IRestriction> Restrictions { get; set; }
}
public interface IRestriction
{
object Limit { get; }
}
public interface IRestriction<T> : IRestriction
where T:struct
{
// hide IRestriction.Limit
new T Limit {get;}
}
public abstract class RestrictionBase<T> : IRestriction<T>
where T:struct
{
// explicit implementation
object IRestriction.Limit
{
get { return Limit; }
}
// override when required
public virtual T Limit { get; set; }
}
public class TimeRestriction : RestrictionBase<TimeSpan>
{
}
public class AgeRestriction : RestrictionBase<TimeSpan>
{
}
public class BlockRule : AbstractBlockRule
{
public override List<IRestriction> Restrictions { get; set; }
}
I also showed using a base restriction class here, but it is not required.
The runtime treats IRestriction<TimeSpan> and IRestriction<int> as different distinct classes (they even have their own set of static variables). In your case the only classes common to both IRestriction<TimeSpan> and IRestriction<int> in the inheritance hierarchy are IRestriction and object.
So indeed, having a list of IRestriction is the only sensible way to go.
As a side note: you have a property Limit in there that you might want to access regardless of whether you're dealing with an IRestriction<TimeSpan> or IRestriction<int>. What I would do in this case is to define another property object Limit { get; } on IRestriction, and hide it in the actual implementation. Like this:
public interface IRestriction
{
object Limit { get; }
}
public interface IRestriction<T> : IRestriction
where T : struct
{
new T Limit { get; set; }
}
public class TimeRestriction : IRestriction<TimeSpan>
{
public TimeSpan Limit { get; set; }
// Explicit interface member:
// This is hidden from IntelliSense
// unless you cast to IRestriction.
object IRestriction.Limit
{
get
{
// Note: boxing happens here.
return (object)Limit;
}
}
}
This way you can access Limit as object on all your IRestriction when you don't care what type it is. For example:
foreach(IRestriction restriction in this.Restrictions)
{
Console.WriteLine(restriction.Limit);
}
Interfaces are contracts that need to be followed by the entity that implements the contract.
You have created two contract with the same name IRestriction
As far as I can see, what you are basically may need is a flag for classes that can be restricted, which should implement the IRestriction non-generic interface.
The second interface seems to be restrictable objects that also contain a limit property.
Hence the definition of the second IRestriction interface can be ILimitRestriction or whatever name suits your business needs.
Hence ILimitRestriction can inherit from IRestriction which would mark classes inheriting ILimitRestriction still objects of IRestriction
public abstract class AbstractBlockRule
{
public long Id{get;set;}
public abstract List<IRestriction> Restrictions {get;};
}
public interface IRestriction{}
public interface IRestrictionWithLimit<T>:IRestriction where T:struct
{
T Limit {get;}
}
public TimeRestriction:IRestrictionWithLimit<TimeSpan>
{
public TimeSpan Limit{get;set;}
}
public AgeRestriction:IRestrictionWithLimit<int>
{
public int Limit{get;set;}
}
public class BlockRule:AbstractBlockRule
{
public virtual List<IRestriction> Restrictions {get;set;}
}

How to automatically copy a property declaration to base class

I have a property A in all subclasses of base class Base.
How can I generate an abstract property definition of property A into base class Base?
I know ReSharper's refactoring Pull Members Up, but that moves the property to base class.
I need an abstract property in base class and a overriding properties in all sub classes. Is there a refactoring in Visual Studio or in ReSharper that can do it automatically for me?
There is a checkbox "Make abstract" for that in ReSharper Pull Members Up dialog :
I'm not sure Resharper can move up and create an abstraction as you want automatically, but you can atleast define it manually like this
In abstract class:
public abstract double A
{
get;
}
In Sub class:
public override double A
{
get
{
return 3.141;
}
}
It might be a clearner design to define a new Interface (or use an existing one) and define the property in the interface. That way, your existing subclasses won't have to use override.
public interface IInterface {
string MyProperty { get; }
}
public class Class : IInterface {
public string MyProperty { get; set; }
}
public abstract class AbstractClass {
public abstract string Value { get; }
}
public class ConcreteClass : AbstractClass {
private string m_Value;
public override string Value {
get { return m_Value; }
}
public void SetValue(string value) {
m_Value = value;
}
}
I hope this will be helpful to you.

Override get, but not set

I have an abstract class that defines a get, but not set, because as far as that abstract class is concerned, it needs only a get.
public abstract BaseClass
{
public abstract double MyPop
{get;}
}
However, in some of the derive class, I need a set property, so I am looking at this implementation
public class DClass: BaseClass
{
public override double MyPop
{get;set;}
}
The problem is, I got a compilation error, saying that
*.set: cannot override because *. does not have an overridable set accessor.
Even though I think that the above syntax is perfectly legitimate.
Any idea on this? Workaround, or why this is so?
Edit: The only approach I can think of is to put both get and set as in the abstract class, and let the subclass throws a NotImplementedException if set is called and it's not necessary. That's something I don't like, along with a special setter method .
One possible answer would be to override the getter, and then to implement a separate setter method. If you don't want the property setter to be defined in the base, you don't have many other options.
public override double MyPop
{
get { return _myPop; }
}
public void SetMyPop(double value)
{
_myPop = value;
}
New in C# 6.0:
If you are only calling the setter within your constructor, you can resolve this problem using read-only properties.
void Main()
{
BaseClass demo = new DClass(3.6);
}
public abstract class BaseClass
{
public abstract double MyPop{ get; }
}
public class DClass : BaseClass
{
public override double MyPop { get; }
public DClass(double myPop) { MyPop = myPop;}
}
It is not possible to do what you want. You have to define the setter in the abstract property, otherwise you won't be able to override it properly.
The only case I know where a getter is defined and a getter/setter are implemented is by using an interface:
public interface IBaseInterface
{
double MyPop { get; }
}
public class DClass : IBaseInterface
{
public double MyPop { get; set; }
}
If BaseClass is in your own codebase, then you can do:
abstract public class BaseClass
{
abstract public double MyPop { get; protected set; }
}
public class DClass : BaseClass
{
private double _myProp;
public override double MyProp
{
get { return _myProp; }
protected set { _myProp = value; }
}
}
EDIT: You can then go make a public method in DClass SetMyProp(double myProp) or the like. The class design for your domain model should be clear about or speak for itself why you can't set the property directly in the base class and why you can do so in the derived one.
Are you sure that doing what you are trying to do would be a good design if you found a way to do it?
It would allow objects of the subclass to make state changes that objects of the parent class can not make. Wouldn't that violate the Liskov Substitution Principle?
You could do something like this:
abstract class TestBase
{
public abstract int Int { get; }
}
class TestDerivedHelper : TestBase
{
private int _Int;
public override int Int
{
get
{
return _Int;
}
}
protected void SetInt(int value)
{
this._Int = value;
}
}
class TestDerived : TestDerivedHelper
{
public new int Int
{
get { return base.Int; }
set { base.SetInt(value); }
}
}
Using TestDerived will have the functionality you're looking for. The only drawback I can see from this method is that you have to implement every abstract method in TestDerivedHelper, but it gives you more control later.
Hope this helps. ;)
The reason that this is not possible is due to the way parameters are "Magicked" into existence by C#. When you define a parameter, C# creates a private field that the implicit getter and setter manipulate. If there is no setter in the base class, it's impossible to change this variable from a method written in a sub class (as the private flag prohibits even sub classes from accessing it). What usually happens is it uses the implicit setter of the base class instead.
I wouldn't advise putting the set in the base class if not all sub classes can do it, because this goes against the whole principle of polymorphic programming (any abstract method defined in the abstract class must be implemented by a subclass). Creating a special setter method, as described in other answers is probably the best way go.
Siege
abstract class TestBase
{
public abstract int Int { get; }
}
class TestDerivedHelper : TestBase
{
private int _Int;
public override int Int
{
get
{
return _Int;
}
}
protected void SetInt(int value)
{
this._Int = value;
}
}
class TestDerived : TestDerivedHelper
{
public new int Int
{
get { return base.Int; }
set { base.SetInt(value); }
}
}
Using TestDerived will have the functionality you're looking for. The
only drawback I can see from this method is that you have to implement
every abstract method in TestDerivedHelper, but it gives you more
control later.
I use this approach and works very well for me.
Also, I made my "TestDerivedHelper" class abstract too, then all the methods must be implemented on "TestDerived" class.
Even though this thread is old I'm positing my solution, in case it helps someone. It is not my own but is based off answers in other SO topics.
public abstract BaseClass
{
public double MyPoP { get { return GetMyPoP; } }
protected abstract double GetMyPoP { get; }
}
public class DClass: BaseClass
{
public new double MyPoP { get; set; }
protected override double GetMyPop { get { return MyPoP; } }
}
This solution adds an extra line of code for each such property that needs accessor modified. However, there is no change to external visibility and provides needed functionality.
public abstract class BaseClass
{
public abstract double MyPop { get; }
}
public class DClass: BaseClass
{
private double _myPop = 0;
public override double MyPop
{
get { return _myPop; }
}
// some other methods here that use the _myPop field
}
If you need to set the property from outside DClass then maybe it would be better to put the setter into the base class.
EDIT:
OK I may have been hasty with this response, but I've given it some more thought now.
Do you have to use an abstract base class? If it's not required, try this:
public interface ISomeRelevantName
{
double MyPop { get; }
}
public class DClass : ISomeRelevantName
{
public double MyPop { get; set; }
}
Why not just have a property in the base class that has a private setter, then in your subclass that needs the setter, override it and make it public.
You cannot override the set accessor since the base class has no set accessor defined.
What you can do is use the new keyword to hide the base classes implementation, but that may not be what you want.

Categories