About Inheritance - c#

Why does this code produce the output "Base class" and not "Derived2 class"?
namespace TestConsoleApplication
{
class Baseclass
{
public void fun()
{
Console.Write("Base class" + " ");
}
}
class Derived1: Baseclass
{
new void fun()
{
Console.Write("Derived1 class" + " ");
}
}
class Derived2: Derived1
{
new void fun()
{
Console.Write("Derived2 class" + " ");
}
}
class Program
{
public static void Main(string[ ] args)
{
Derived2 d = new Derived2();
d.fun();
}
}
}

Because you didn't declare the method as public.
You've told it to hide the original definition, rather than override it - which it will do, but the default access modifier is private, not public.
For example, when calling the method from within Derived2:
class Derived2 : Derived1
{
new void fun()
{
Console.Write("Derived2 class" + " ");
}
public void Test()
{
fun();
}
}
class Program
{
public static void Main(string[] args)
{
Derived2 d = new Derived2();
d.Test(); //Prints 'Derived2 class'
}
}
Setting it to public will indeed print Derived2 in your original example
public new void fun()
{
Console.Write("Derived2 class" + " ");
}

Related

"CS0109: The member 'member' does not hide an inherited member. The new keyword is not required" - is this actually true?

I've read other threads and Eric Lippert's posts on the subject, but haven't seen this exact situation addressed anywhere.
C# optional parameters on overridden methods
Optional parameters and inheritance
I'm trying to implement the following situation:
public class BaseClass
{//ignore rest of class for now
public void DoThings(String str)
{
//dostuff
}
}
public class DerivedClass: BaseClass
{//ignore rest of class for now
new public void DoThings(String str, Int32 someint = 1)
{
//dostuff but including someint, calls base:DoThings in here
}
}
When I do this the compiler gives me the warning in the subject line that I do not need to use the new keyword because the method does not hide the inherited method. However I do not see a way to call the base method from the object instance, so it looks hidden to me.
I want it to actually be hidden. If it is not hidden, there is potential for some other user to some day call the base method directly and break the class (it involves thread safety).
My question is, does the new method actually hide the inherited method (compiler is wrong?) or is the compiler correct and I need to do something else to hide the original method? Or is it just not possible to achieve the desired outcome?
void DoThings(String str) accepts a single parameter
void DoThings(String str, Int32 someint = 1) accepts two parameters
=> the methods are distinct, unrelated methods, which incidentally share the name.
Default parameters are inserted at the call-sites during compilation.
Here is one possible solution:
public class BaseClass
{
public virtual void DoThings(String str)
{
//dostuff
}
}
public class DerivedClass: BaseClass
{
public override void DoThings(String str)
{
DoThings(str, 1); // delegate with default param
}
public void DoThings(String str, Int32 someint)
{
//dostuff
}
}
Note that new makes it possible to call base classes' virtual methods in the first place by having a reference with static type of the base class (e.g. by casting it to the base class):
public class Test
{
public static void Main()
{
var obj = new DerivedClass();
BaseClass baseObj = obj;
obj.DoThings("a");
baseObj.DoThings("b");
((BaseClass)obj).DoThings("c");
}
}
class BaseClass
{
public void DoThings(String str)
{
Console.WriteLine("base: " + str);
}
}
class DerivedClass: BaseClass
{
new public void DoThings(String str, Int32 someint = 1)
{
Console.WriteLine("derived: " + str);
base.DoThings(str);
}
}
Output:
derived: a
base: a
base: b
base: c
If you want callers to never call the overridden method of a base class, mark it virtual and override it (like already shown at the top of this answer):
public class Test
{
public static void Main()
{
var obj = new DerivedClass();
BaseClass baseObj = obj;
obj.DoThings("a");
baseObj.DoThings("b");
((BaseClass)obj).DoThings("c");
}
}
class BaseClass
{
public virtual void DoThings(String str)
{
Console.WriteLine("base: " + str);
}
}
class DerivedClass: BaseClass
{
// "hide" (override) your base method:
public override void DoThings(String str)
{
// delegate to method with default param:
this.DoThings(str);
}
public void DoThings(String str, Int32 someint = 1)
{
Console.WriteLine("derived: " + str);
base.DoThings(str);
}
}
Output:
derived: a
base: a
derived: b
base: b
derived: c
base: c
After discussion in the comments: you do not want to use inheratince here, but rather opt for compisition.
The code could look like the following:
public class Test
{
public static void Main()
{
var obj = new DerivedClass(new BaseClass());
obj.DoThings("a");
// baseObj.DoThings("b"); // not accessible
// ((BaseClass)obj).DoThings("c"); // InvalidCastException!
}
}
class BaseClass
{
public void DoThings(String str)
{
Console.WriteLine("base: " + str);
}
}
class Wrapper
{
private BaseClass original;
public Wrapper(BaseClass original) {
this.original = original;
}
public void DoThings(String str, Int32 someint = 1)
{
Console.WriteLine("wrapped: " + str);
original.DoThings(str);
}
}
Output:
base: a
wrapped: a
the 'new' keyword can't be used where you used it
To hide the member:
public class BaseClass
{ // ignore rest of class for now
public virtual void DoThings(String str)
{
// dostuff
}
}
public class DerivedClass: BaseClass
{ //ignore rest of class for now
public override void DoThings(String str)
{
// dostuff
}
public void DoThings(String str, Int32 someint = 1)
{
// do stuff but including some int, calls base:DoThings in here
}
}

Using base class and base interface in C#

I am reshaping an entire system that does not use base classes and base interfaces.
My idea to do so is to extract all the common methods to a base classes and base interfaces.
So basically, we would have:
A base class SomeClassBase implementing an interface ISomeClassBase
A derived class SomeClassDerived implementing ISomeClassDerived (this interface deriving from ISomeClassBase)
Now the problem, how can I instantiate "_mySession" in the derived class (which has a different cast than in the base class), while preserving all the methods from the base class:
public class SomeClassBase : ISomeClassBase
{
public IMySessionBase _mySession = MySession.Instance();
public SomeClassBase ()
{
_mySession.connect(); // Needed??
}
public void doSomething()
{
_mySession.doSomething();
}
}
public class SomeClassDerived : SomeClassBase, ISomeClassDerived
{
public IMySessionDerived _mySession = MySession.Instance();
public SomeClassDerived ()
{
_mySession.connect();
}
public void doSomethingElse()
{
_mySession.doSomethingElse();
}
}
One more thing, IMySessionDerived implements IMySessionBase.
Do not redefine _mySession Let it come from base class.
However in you Derived class you can still reassign.
public class SomeClassDerived : SomeClassBase, ISomeClassDerived
{
public SomeClassDerived ()
{
_mySession = MySession.Instance(); //Declaration comes from base class automatically
_mySession.connect();
}
public void doSomethingElse()
{
_mySession.doSomethingElse();
}
}
If your IMySessionBase and IMySessionDerived are following Hierarchy, it should work. But in some rare cases, You might end up getting into a DoubleDispatchProblem.
As Pointed out in commens, If you want to do something from IMySessionDerived you can add a Property.
public class SomeClassDerived : SomeClassBase, ISomeClassDerived
{
IMySessionDerived _derivedSessionAccessor=> _mySession as IMySessionDerived;
}
Update: To fix the exact design problem here,
Instead of deriving from the base class, have it as a field. And inherit from interface. So Instead of doing above approach,
do like,
public class SomeClassBase : ISomeClassBase
{
public IMySessionBase _mySession ;
public SomeClassBase ( IMySessionBase session)
{
_mySession=session;
_mySession.connect(); // Needed??
}
public void doSomething()
{
_mySession.doSomething();
}
}
public class SomeClassDerived : , ISomeClassDerived
{
public IMySessionDerived _mySession = MySession.Instance();
private SomeClassBase _baseClassInstance;
public SomeClassDerived ()
{
_baseClassInstance=new SomeClassBase(_mySession);
//_mySession.connect();
}
public void doSomethingElse()
{
_baseClassInstance.doSomethingElse();
}
}
Pasting #Selvin answer instead of the link buried in the comments:
The trick here is to use the keyword "base()"
using System;
using System.Runtime.CompilerServices;
public class Program
{
public static void Main()
{
var o1 = new O1();
o1.DS1();
var o2 = new O2();
o2.DS1();
o2.DS2();
}
public class Session1
{
protected readonly Type ownerType;
public Session1(Type type)
{
ownerType = type;
}
public virtual void DS1([CallerMemberName] string functionName = "")
{
Console.WriteLine(ownerType.Name + ":" + GetType().Name + ":" + functionName);
}
}
public class Session2 : Session1
{
public Session2(Type type):base(type) { }
public virtual void DS2([CallerMemberName] string functionName = "")
{
Console.WriteLine(ownerType.Name + ":" + GetType().Name + ":" + functionName);
}
}
public class O1
{
private readonly Session1 t;
public O1() : this(new Session1(typeof(O1))) { }
protected O1(Session1 t)
{
this.t = t;
}
public void DS1()
{
t.DS1();
}
}
public class O2 : O1
{
private readonly Session2 t;
public O2() : this(new Session2(typeof(O2))) { }
protected O2(Session2 t) : base(t)
{
this.t = t;
}
public void DS2()
{
t.DS2();
}
}
}

Please correct me with OOP inheritance

I thought it will call the derived class function because class will give importance to its own function but it is calling base class function please correct me...
class Baseclass
{
public void fun()
{
Console.Write("Base class" + " ");
}
}
class Derived1 : Baseclass
{
new void fun()
{
Console.Write("Derived1 class" + " ");
}
}
class Derived2 : Derived1
{
new void fun()
{
Console.Write("Derived2 class" + " ");
}
}
class test
{
static void Main(string[] args)
{
Derived2 d = new Derived2();
d.fun();
}
}
The base class method is called because only the base class method is accessible.
Why aren't the other methods accessible? Let's look at the method in Derived2:
new void fun()
{
Console.Write("Derived2 class" + " ");
}
What is its access modifier? None, so it defaults to private. This means that you can't access this method from test class!
To make it work, simply add a public modifer:
new public void fun()
{
Console.Write("Derived2 class" + " ");
}

How can I access the result in Derived 1 and Derived 2 and not the base class

class Baseclass
{
public void fun()
{
Console.Write("Base class" + " ");
}
}
class Derived1 : Baseclass
{
new void fun()
{
Console.Write("Derived1 class" + " ");
}
}
class Derived2 : Derived1
{
new void fun()
{
Console.Write("Derived2 class" + " ");
}
}
class Program
{
public static void Main(string[] args)
{
Derived2 d = new Derived2();
Derived1 e = new Derived1();
d.fun();
e.fun();
}
}
How can I access the result in Derived 1 and Derived 2 and not the base class
Is this overloading or overriding?
new is neither overloading nor overriding. It essentially says 'When I am called, and the object is cast as Derived1, then invoke this'. Note that it's when the object is cast, rather than whenever the object is interacted with.
Your code would appear to work, if you had marked the methods as public. For example:
class Derived1 : Baseclass
{
public new void fun()
{
Console.Write("Derived1 class" + " ");
}
}
class Derived2 : Derived1
{
public new void fun()
{
Console.Write("Derived2 class" + " ");
}
}
Would print
Derived2 class Derived1 class
However, changing your code to the following will reveal the problem with new in this case:
void Main()
{
Derived2 d = new Derived2();
Derived1 e = new Derived1();
ExecuteIt(d);
ExecuteIt(e);
}
void ExecuteIt(Baseclass obj)
{
obj.fun();
}
Prints
Base class Base class
Since the object is cast as Baseclass, and thus the hiding doesn't take effect. To properly implement overriding, you need to do the following:
class Baseclass
{
public virtual void fun()
// ^^^^^^^
{
Console.Write("Base class" + " ");
}
}
class Derived1 : Baseclass
{
public override void fun()
// ^^^^^^ ^^^^^^^^
{
Console.Write("Derived1 class" + " ");
}
}
class Derived2 : Derived1
{
public override void fun()
// ^^^^^^ ^^^^^^^^
{
Console.Write("Derived2 class" + " ");
}
}
Which, when run with:
void Main()
{
Derived2 d = new Derived2();
Derived1 e = new Derived1();
ExecuteIt(d);
ExecuteIt(e);
}
void ExecuteIt(Baseclass obj)
{
obj.fun();
}
Properly outputs
Derived2 class Derived1 class

Optional Parameters in Abstract method? Is it possible?

I have a abstract base class.
I have 2 derived classes from this base class.
Is there anyway that one of my classes can ignore the string parameter in the abstract overide usage?
Or do I have to just send in a blank one and ignore it? (making readability drop slightly)
Can I have one function that has some sort of optional parameter so that both of the following derived classes would compile?
PS - The following code is riddled with in-compilable code for the example of what I would like to do
PS PS - Yes i have compiled the following code already - see above comment for outcome
public abstract class MyBaseClass
{ //optional string?
public abstract void FunctionCall(int i, string s = "");
}
public class MyDerivedClass : MyBaseClass
{
public override void FunctionCall(int i)
{
MessageBox.Show(i.ToString());
}
}
public class YourDerivedClass : MyBaseClass
{
public override void FunctionCall(int i, string s)
{
MessageBox.Show(s + " " + i.ToString());
}
}
If you don't absolutely need FunctionCall to be abstract, you can declare two versions of it:
public abstract class MyBaseClass
{
public virtual void FunctionCall(int i)
{
this.FunctionCall(i, "");
}
public virtual void FunctionCall(int i, string s)
{
}
}
public class MyDerivedClass : MyBaseClass
{
public override void FunctionCall(int i)
{
MessageBox.Show(i.ToString());
}
}
public class YourDerivedClass : MyBaseClass
{
public override void FunctionCall(int i, string s)
{
MessageBox.Show(s + " " + i.ToString());
}
}
Otherwise, if it must be abstract to ensure it is implemented, you could still add two versions, it just makes the inheritors more verbose:
public abstract class MyBaseClass
{
public abstract void FunctionCall(int i);
public abstract void FunctionCall(int i, string s);
}
public class MyDerivedClass : MyBaseClass
{
public override void FunctionCall(int i, string s)
{
throw new NotImplementedException();
}
public override void FunctionCall(int i)
{
MessageBox.Show(i.ToString());
}
}
public class YourDerivedClass : MyBaseClass
{
public override void FunctionCall(int i)
{
throw new NotImplementedException();
}
public override void FunctionCall(int i, string s)
{
MessageBox.Show(s + " " + i.ToString());
}
}
It will throw a compile error: "Abstract Inherited member 'MyBaseClass.FunctionCall(int, string)' is not implemented".
So no, the short answer is you can't do this.
Instead, you would have to do method overloading and implement BOTH abstract methods.
public abstract class MyBaseClass
{
public abstract void FunctionCall(int i);
public abstract void FunctionCall(int i, string s = "");
}
public class MyDerivedClass : MyBaseClass
{
public override void FunctionCall(int i, string s = "") { }
public override void FunctionCall(int i)
{
MessageBox.Show(i.ToString());
}
}
public class YourDerivedClass : MyBaseClass
{
public override void FunctionCall(int i, string s)
{
MessageBox.Show(s + " " + i.ToString());
}
public override void FunctionCall(int i) {}
}
However this seems quite messy. Perhaps the best option is to always use the optional parameter and simply not pass in a value if it is not needed or handle it as you already seem to be doing.
public class MyDerivedClass : MyBaseClass
{
public override void FunctionCall(int i, string s = "")
{
if (!string.IsNullOrEmpty(s))
MessageBox.Show(i.ToString());
else
// handle other path here
}
}
One possible way is to use extension methods to add missing overrides (which also works with interfaces)
static class MyBaseClassExtensions
{
public void FunctionCall(MyBaseClass this item, int i)
{
item.FunctionCall(i, null);
}
}

Categories