Using a subclass method on a base class object - c#

Let's say I have declared the following classes:
class BaseClass{
/* properties, constructors, getters, setters etc. */
public static BaseClass Create(string url){
/*will return, depending on url, a BaseClass or a SubClass object*/
}
public void Method(){
/* some code here */
}
}
class SubClass: BaseClass{
/* other properties, constructors, getters, setters etc. */
new public void Method(){
/* some other code here */
}
}
Now in my Main method I would like to do something along the lines of:
BaseClass baseClass = BaseClass.Create(url);
if(baseClass.GetType()==typeof(SubClass)){
baseClass.Method();
}
The idea here, of course, is to use Method as it is implemented in SubClass. It may be a silly question but how do I do that? I can't cast a base class into a subclass so I'm not sure...
EDIT
Clarified my question. Even though baseClass was declared as a BaseClass instance, baseClass is SubClass will return trueif url is such that Create returns a SubClass instance.

It looks like you might be looking for polymorphism, but I can't be sure from the description. What is the concrete use case for what you're trying to do?
class BaseClass{
public virtual void Method(){
Console.WriteLine("BaseClass");
}
}
class SubClass : BaseClass{
/* other properties, constructors, getters, setters etc. */
public override void Method(){
Console.WriteLine("SubClass");
}
}
static class Test
{
public void go() {
BaseClass instance = new SubClass();
instance.Method(); // prints "SubClass"
}
}
If it doesn't make sense for the base class to have an implementation, then declare the class and the method as abstract -- this forces the derived classes to override the method, guaranteeing that any instantiated class instance will have a valid implementation.

Well I don't know why you would want to do that?
There is no way that the type of an instance of BaseClass will be equal to the type of SubClass.
That could only be possible if you created a instance of SubClass and then cast it to BaseClass. But in that case you could just cast it back to SubClass to call Method()

If you instansiate the baseClass as BaseClass you will not be able to call the method as SubClass, but if you write
BaseClass baseClass = new SubClass();
if (baseClass is SubClass)
{
SubClass subClass = baseClass as SubClass;
subClass.Method();
}
it will call the method as the SubClass is defined.

First of all: you have to initialise your variable as an instance of SubClass, otherwise there is no way.
Then declare the method in the base class virtual,
or
cast the object to SubClass, and call the Method that way.
So either
class BaseClass{
/* properties, constructors, getters, setters etc. */
virtual public void Method(){
/* some code here */
}
}
or
((SubClass)baseClass).Method();

Related

Inheriting constructor with single optional argument

I have a set of classes that inherit from a base...
public abstract class BaseClass
{
public BaseClass()
{
// ...
}
}
public abstract class BaseMessageClass : BaseClass
{
// ...
}
public SpecificMessageClass : BaseMessageClass
{
// ...
}
Instantiating an object like this works:
SpecificMessageClass myMessage = new SpecificMessageClass();
However, I need to change all constructors to have an optional string parameter, like this:
public abstract class BaseClass
{
public BaseClass(string optParam="whatever")
{
// ...
}
}
Now, when I try and instantiate the object with the optional argument:
SpecificMessageClass myMessage = new SpecificMessageClass("coolstring");
I get the error:
'SpecificMessageClass' does not contain a constructor that takes 1 arguments"
Is there ANY way to do this without explicitly declaring the constructors in each level of inherited class?
No.
But given that you want to inherit, I'm guessing you want the same logic to apply at all levels on some inherited field or property. If so, the closest you can get is to add a factory method like a Create<T>(string optParam="whatever") on the base class like the following:
public class BaseClass
{
public static T Create<T>(string optParam="whatever") where T : BaseClass
{
var t = new T(); //which invokes the paramterless constructor
((BaseClass)t).SomePropertyOrFieldInheritedFromTheBaseClass = optParam; //and then modifies the object however your BaseClass constructor was going to.
return t;
}
}
That would allow all implementers of the class to implement the BaseClass and get the same effect as having the optional parameter constructor.
By the way, I didn't test the above code, so you might need to tweak it slightly. But hopefully it gives the idea.
I think that's probably the closest you can get.
Constructors are special methods. If your class specifies no constructors, it will have a no-args constructor that inherits from the parent's no-args constructor. As soon as you specify a single constructor, you do not automatically get any of the parent's constructors for free. You must declare each different constructor you need.

Invoking constructor of derived class execute before constructor of base class

Well, originally I had a couple of constants (like MAX_SPEED) with different values in every of the derived classes. The idea was to use those values in some methods of the base class. That's when I realized that I cannot do that with constants, so I created read-only properties.
I need a method to assign those values to private fields at the moment of the instantiation, preferably in the base class. But first I have to assing the original values in derived classes. Since those are properties, I couldn't find a way to initialize them while defining, so the only way to do that is in the derived constructors.
That's where the problem comes: values are initialized after their assigning to private fields in the base class. The solution I get away with is to create a virtual method and to do assigning there.
Is there a way to call a base constructor from derived class so that the code from derived constructor will be invoked first?
class BaseClass
{
public BaseClass()
{
System.Console.WriteLine("This should be shown after");
}
}
class DerivedClass : BaseClass
{
public DerivedClass() : base()
{
System.Console.WriteLine("This should be shown first");
}
}
Of course in the example it would work the other way around. Is there a solution?
No. The base class constructor is always executed before the body of the derived class constructor. However:
Any instance variable initializers in the derived class are executed before the base class constructor
The base class constructor can execute virtual methods which can be overridden in the derived class. This is almost always a bad idea though. (All kinds of normal preconditions are invalid at this point. You can observe readonly variables which haven't been set yet because they'll be set in the constructor body, for example. Ick.)
To demonstrate both of these:
using System;
class BaseClass
{
public BaseClass()
{
VirtualMethod();
Console.WriteLine("BaseClass ctor body");
}
public virtual void VirtualMethod()
{
Console.WriteLine("BaseClass.VirtualMethod");
}
}
class DerivedClass : BaseClass
{
int ignored = ExecuteSomeCode();
public DerivedClass() : base()
{
Console.WriteLine("DerivedClass ctor body");
}
static int ExecuteSomeCode()
{
Console.WriteLine("Method called from initializer");
return 5;
}
public override void VirtualMethod()
{
Console.WriteLine("DerivedClass.VirtualMethod");
}
}
class Test
{
static void Main()
{
new DerivedClass();
}
}
Output:
Method called from initializer
DerivedClass.VirtualMethod
BaseClass ctor body
DerivedClass ctor body
Additionally, if your base class constructor takes a parameter, then you can execute some code in the derived class in order to provide an argument:
DerivedClass() : base(SomeStaticMethod())
All of these are fairly smelly though. What's your specific situation?
No, you can't do that. Base classes are always initialized first. However, you can do something like this:
class BaseClass
{
public BaseClass()
{
this.Initialize();
}
protected virtual void Initialize()
{
System.Console.WriteLine("This should be shown after");
}
}
class DerivedClass : BaseClass
{
public DerivedClass() : base()
{
}
protected override void Initialize()
{
System.Console.WriteLine("This should be shown first");
base.Initialize();
}
}
One more option is to make child class constructor as static , so that it executes first than parent class constructor. but it not preferable it violates the oop design

How to forbid a class method/property to be overridden in C#?

I believe I want a some methods and properties of a class to be unoverridable and use the base's implementation in all derived classes. How to achieve this? sealed keyword doesn't seem to work and says "method can not be sealed because it is not an override".
Members are sealed by default in C# - unless they're marked as virtual, they can't be overridden in derived classes anyway.
They can be shadowed in derived classes, admittedly:
public new void SomeMethod()
{
}
... but that's not the same as overriding. There's no way you can prevent this, but if a caller uses a compile-time type of the base class, they won't end up calling this accidentally anyway.
If you could give us more details of exactly what you're trying to prevent (from both the caller's POV and the code being called) we may be able to help more.
A method that is not already an override will not be overridable unless you mark it as virtual. So it sounds like in your case no action is needed.
class A
{
public void B() {} // can't override
public virtual C() {} // can override
public virtual D() {} // can override
}
The sealed modifier only applies when a method is already an override of a member in the base class. This allows you to prevent overrides in subclasses of that class.
class A1 : A
{
public void B() {} // shadows A.B. Not a virtual method!
public override C() {} // overrides A.C, subclasses can override
public override sealed D() {} // overrides A.D, subclasses cannot override
// (but can shadow)
}
This isn't possible. A derived class can always use the new keyword to hide (not override) its parents methods. The sealed keyword simply stops the derived class from overriding a virtual method, but it could still use new to hide the base method.
The "sealed" keyword can only be used, if you override a method that is virtual, but don't want a class deriving from your implementation to override it again. Declaring the method not virtual is all you need.
As other pointed out that there is in fact a "new" keyword, which allows hiding the method. But as long as you use a reference of your base class, your base method is always called:
class BaseClass
{
public void Foo() { Console.WriteLine("Foo"); }
}
class Derived : BaseClass
{
public new void Foo() { Console.WriteLine("Bar"); }
}
public static void Main()
{
Derived derived = new Derived();
derived.Foo(); // Prints "Bar"
BaseClass baseClass = derived;
baseClass.Foo(); // Prints "Foo"
}
Since providing a base-class only makes sense, as long as you use a "BaseClass"-pointer everywhere, your method cannot be hidden.
This is precisely what sealed keyword is for.
http://msdn.microsoft.com/en-us/library/ms173150.aspx
A class member, method, field,
property, or event, on a derived class
that is overriding a virtual member of
the base class can declare that member
as sealed. This negates the virtual
aspect of the member for any further
derived class. This is accomplished by
putting the sealed keyword before the
override keyword in the class member
declaration.
If you've overridden a method from base class than use sealed.
If you've declared a method in the class and don't want it to be overridden in any derived classes than don't mark it as virtual. Only virtual members can be overridden.

Run same method in base and derived class

What do I need to do to first run the method in the base class then run the same method in the derived class? Is this a good idea?
I want run common actions in base class and extend it in the derived class in the same method. Is this how it is usually done?
public abstract class MyBase
{
void DoStuff()
{
//some common implementation
}
}
public class MyDerived : MyBase
{
void DoStuff()
{
// DoStuff in the base first
// Then DoStuff in here
}
}
are you talking about something like that?
class base
{
protected virtual void method()
{
// do some stuff in base class, something common for all derived classes
}
}
class derived : base
{
public override void method()
{
base.method(); // call method from base
// do here some more work related to this instance of object
}
}
that's not a bad idea, I do use it a lot when I have some common functionality for all derived classes.
If you want to guarantee that the base class logic is run (and not rely on the derived class being polite), you can do this:
public void Method()
{
//Stuff that should always happen in base class
OnMethod();
}
protected virtual void OnMethod()
{
//Default base class implementation that derived class can either override or extend
}
Use base.TheMethod() to run a method in the base class from a derived class.
If you want to run a method of a derived class from a base class, then you have to cast the base class to the derived class. This means that your class needs to be aware of who is deriving it, which breaks encapsulation and should be avoided.

C# Inheritance concept advise

I have a small query related to OOP concept in C#.
I have an interface
interface intf
{
string Hello();
}
A base class
public class BaseClass
{
public string Hello()
{
return "Hello of base class called";
}
}
A child class that is derived from BaseClass and implements the interface intf as well
public class ChildClass : BaseClass, intf
{
string Hello()
{
return "Hello of child class called";
}
}
Now my question is that when I create an object of ChildClass then when I call the hello method it always calls the hello method of BaseClass. Firstly, why does it call the Hello of the BaseClass? Secondly, how can I call the Hello of the ChildClass?
private void Form1_Load(object sender, EventArgs e)
{
ChildClass obj = new ChildClass();
MessageBox.Show(obj.Hello());
}
First of all, you did not provide an access modifier for Hello in ChildClass. This makes it private by default. To access that method from outside of the class, mark it public (or internal if using it from the same namespace). As it stands now, the only publicly visible Hello method is the base class method.
Secondly, once you have resolved the access issue, Hello will hide the method in the base. If this is intentional, it is advisable to use the new keyword with the method
public new string Hello()
If your intention was not to hide the method but instead to override it, mark the method as virtual in the base class and use the override keyword in the child.
public class ChildClass : BaseClass, intf
{
public override string Hello()
{
return "Hello of child class called";
}
}
public class BaseClass
{
public virtual string Hello()
{
return "Hello of base class called";
}
}
This will allow you to always call the child method unless you explicitly call the base method from within the child.
Calls like this from the outside world
((BaseClass)child).Hello();
(child as BaseClass).Hello();
BaseClass baseClass = new ChildClass();
baseClass.Hello();
Will result in the child method being used.
Calls like this from within the child class
base.Hello();
Will result in the base class method being used.
Why call the Hello of base
Your child class implements the interface, so it is considered to contain a public Hello method. But in your child class, Hello is not public. The Hello method in base class is public and is considered to be the implementation of the interface.
How to call Hello of child class
Make the Hello in child class public. Then it will be considered to an implementation of the interface.
Declare the method in the base class virtual and then override it in the child class. That way, the virtual call will resolve to the child class instead of the parent class.
Update:
To answer the question about why it still the base method even after you put new in the method declaration:
By default, class members are private. Therefore, since you did not mark the method as public, the method is private. Therefore the programs is force to called the base method as it's the only one that's accessible.
The way you've currently declared your methods, the method Hello() in the ChildClass in inaccessible, and hence the public method in the BaseClass is called. What you really want is what Esteban said though, declare the base method public virtual, the derived method public override, otherwise your method is just shadowing the base class method.
As other said, make the Hello method in the Child class public override.
Also, IMHO, you should implement the interface in the base class, not the child class. But that has nothing to do with the fact your method doesn't get called.

Categories

Resources