Abstract and virtual functions - c#

I am trying to implement two level inheritance. Currently, there is an abstract class and an inherited class :
public abstract class A
{
public abstract void func();
}
public class B : A
{
public override void func()
{
.......
}
}
I would like to create two specialized instances of class B but I want those functions to be exposed by class A. I am going for,
public abstract class A
{
public abstract void func();
}
public class B : A
{
public virtual void func();
}
public class C : B
{
public override void func()
{
........
}
}
public class D : B
{
public override void func()
{
........
}
}
This implementation is wrong but that is my intent. How will I implement this ?

You can use interface instead of abstract class A like this:
public interface A
{
void func();
}
public abstract class B: A
{
public abstract void func();
}
public class C : B
{
public override void func()
{
throw new NotImplementedException();
}
}
public class D : B
{
public override void func()
{
throw new NotImplementedException();
}
}
May be it helps you.

You cannot have virtual method without implementation, so instead you should make class B abstract, which should make compiler happy:
public abstract class B : A
{
}
Alternative approach is to add empty method body for function func:
public class B : A
{
public virtual void func()
{
// function has empty method body
// it does not do anything, but you can override functionality in derived classes
}
}

Related

Abstract class implementation design

Currently I have made a design where my BaseClass is the guideline of how my program has to behave. I have made an abstract method DoWork() , the inheritors have to implement this method.
The thing is Class C overrides Setup() so it doesn't need DoWork() anymore. Now I am left with a throw new NotImplementedException();
Question: Is there a way how to improve my design so I won't have those methods with NotImplementedException?
public abstract class BaseClass
{
public virtual void Setup()
{
DoWork();
FinnishWork();
Environment.Exit(0);
}
public abstract void DoWork();
public abstract void FinnishWork();
}
public class A : BaseClass
{
public override void DoWork()
{
Console.WriteLine('A');
}
public override void FinnishWork()
{
Console.WriteLine('FinnishA');
}
}
public class B : BaseClass
{
public override void DoWork()
{
Console.WriteLine('B');
}
public override void FinnishWork()
{
Console.WriteLine('FinnishB');
}
}
public class C : BaseClass
{
public override void Setup()
{
FinnishWork();
Console.WriteLine('C');
}
public override void DoWork()
{
throw new NotImplementedException();
}
public override void FinnishWork()
{
Console.WriteLine('FinnishC');
}
}
As class C doesn't implement DoWork() it shouldn't really inherit from your abstract class.
You can only inherit from one class, but you can implement many interfaces.
In many ways it is simpler to deal with interfaces than abstract classes. Base classes, whether abstract or not really come into their own if they perform some function that you may wish to provide to you inheriting classes. An abstract class with empty methods isn't any better than an interface.
Consider something like:
public interface IDoWork
{
void DoWork();
}
public interface IBase
{
void Setup();
void FinnishWork();
}
public abstract class BaseClass : IBase, IDoWork
{
public virtual void Setup()
{
DoWork();
FinnishWork();
Environment.Exit(0);
}
public abstract void FinnishWork();
public abstract void DoWork();
}
public class A : BaseClass
{
public override void DoWork()
{
Console.WriteLine('A');
}
public override void FinnishWork()
{
Console.WriteLine("FinnishA");
}
}
public class B : BaseClass
{
public override void DoWork()
{
Console.WriteLine('B');
}
public override void FinnishWork()
{
Console.WriteLine("FinnishB");
}
}
public class C : IBase
{
public void Setup()
{
FinnishWork();
Console.WriteLine('C');
}
public void FinnishWork()
{
Console.WriteLine("FinnishC");
}
}
Examples in use:
IBase instanceA = new A();
BaseClass instanceB = new B();
IBase instanceC = new C();
instanceA.Setup();
instanceB.Setup();
instanceC.Setup();
instanceB.DoWork();
You're inheriting in too few steps. You need BaseClassLite and BaseClassHeavy to make this work.
Start with this:
public abstract class BaseClassLite
{
public virtual void Setup()
{
FinnishWork();
Environment.Exit(0);
}
public abstract void FinnishWork();
}
public abstract class BaseClassHeavy : BaseClassLite
{
public override void Setup()
{
DoWork();
base.Setup();
}
public abstract void DoWork();
}
(Or give them more meaningful names.)
Then you implement your classes like this:
public class A : BaseClassHeavy
{
public override void DoWork()
{
Console.WriteLine("A");
}
public override void FinnishWork()
{
Console.WriteLine("FinnishA");
}
}
public class B : BaseClassHeavy
{
public override void DoWork()
{
Console.WriteLine("B");
}
public override void FinnishWork()
{
Console.WriteLine("FinnishB");
}
}
public class C : BaseClassLite
{
public override void Setup()
{
base.Setup();
Console.WriteLine("C");
}
public override void FinnishWork()
{
Console.WriteLine("FinnishC");
}
}
The idea to have a Setup method in BaseClass while having 2 abstracts methods to implement is good (it is even given a name: template method pattern).
However there is one problem lying in how Setup() is declared in BaseClass: you made it virtual which goes against the principle that you want to enforce:
BaseClass is the guideline of how my program has to behave
It is now possible to override it (like you did in C) and break the behavior you want to enforce.
First, remove virtual in BaseClass then override DoWork in C as follow:
public override void DoWork() { }
Having this kind of empty method is a sign of a flawed abstraction (does C really need to inherit from BaseClass ?) but I can't help more if you don't provide more context about the real meaning and names of these classes/methods.
Use a second base class to be inherited from class C:
public abstract class BaseBaseClass
{
public virtual void Setup()
{
FinnishWork();
Environment.Exit(0);
}
...
}
public abstract class BaseClass : BaseBaseClass
{
public abstract void DoWork();
...
}
public class C : BaseBaseClass {...}

Using operator sealed with the members of the class

I've found in the Troelsen's book, that operator sealed can be used on the members of the class to protect virtual methods from the override.
But if I don't want to override a virtual methods, what sense to make it virtual?
You might have a situation like this:
public class A
{
public virtual void MyMethod()
{
//...
}
}
public class B : A
{
public override void MyMethod()
{
//...
}
}
public class C : B
{
public override void MyMethod()
{
//...
}
}
But what if you want for the inheriting class C NOT to be able to override B's MyMethod, while still allowing B to override A's? Then you can do:
public class B : A
{
public sealed override void MyMethod()
{
//...
}
}
With this change made, you can no longer override the method in C.
In this context, consider the following example:
public class A
{
public virtual void SomeMethod() { }
}
public class B : A
{
public sealed override void SomeMethod() { }
}
public class C : B
{
public override void SomeMethod() { }
}
In this example, without the use of the sealed keyword on SomeMethod in class B, class C would be able to override it because it's original declaration was as virtual. The sealed keyword in this context generates a compiler error. See the MSDN for more information.

C# how to override like this?

the code below is saying a() cannot override a() as wee.a() is not marked virtual, abstract or override. Is there a a way around this? I need to have code inside the super method, but still want to override it!
public abstract class wee
{
public void a()
{
}
}
public class dee : wee
{
public override void a()
{
}
public void b()
{
}
}
You need to mark wee.a virtual or abstract.
Virtual:
public abstract class wee
{
public virtual void a()
{
}
}
public class dee : wee
{
public override void a()
{
}
public void b()
{
}
}
Abstract:
public abstract class wee
{
public abstract void a();
}
public class dee : wee
{
public override void a()
{
}
public void b()
{
}
}
It will not override the method, there is no way to do this without marking the base as such. If you don't want to modify the base as others have suggested, instead you can hide the base method like this:
public class dee : wee
{
public new void a()
{
}
public void b()
{
}
}
Mark wee.a() as virtual -- it allows you to provide a base implementation but gives the option to override that behavior in subclasses if needed.
// wee
public virtual void a() { // do stuff for base implementation }
// dee
public override void a() { // override behavior implemenation }

How to override a method inherited from a base class, which in turn implemented it from an interface?

I have a class B that inherits from class A, which in turn inherits from interface I. This interface exposes a method M which, of course, is implemented by A, but I would like to override it in B. Moreover, I would like to call A.M from B.M. How do I do that?
EDIT: The answers made me feel kind of stupid, especially since I know what virtual means and, in fact, I have tried it:
class A
{
virtual void I.M() // fails
I never even considered not implementing the interface explicitly.
Thank you all.
Well, either you need to make the method virtual in A, or you need to reimplement the interface in B, which gets messy. Here's the simpler version:
using System;
public interface IFoo
{
void M();
}
public class A : IFoo
{
public virtual void M()
{
Console.WriteLine("A.M");
}
}
public class B : A
{
public override void M()
{
base.M();
Console.WriteLine("B.M");
}
}
class Test
{
static void Main()
{
IFoo foo = new B();
foo.M();
}
}
... and here's the version which reimplements IFoo, hiding A.M() instead of overriding it:
using System;
public interface IFoo
{
void M();
}
public class A : IFoo
{
public void M()
{
Console.WriteLine("A.M");
}
}
public class B : A, IFoo
{
public new void M()
{
base.M();
Console.WriteLine("B.M");
}
}
class Test
{
static void Main()
{
IFoo foo = new B();
foo.M();
}
}
Note that if you then had:
A a = (A) foo;
a.M();
it would only call A.M(), not B.M().
You can use the New keyword to hide the base M as well, heres a short linqpad program
The diffrence between virtual and new
http://blogs.msdn.com/b/csharpfaq/archive/2004/03/12/what-s-the-difference-between-code-override-code-and-code-new-code.aspx
void Main()
{
var x = new B();
x.M();
}
public interface I
{
void M();
}
public class A : I
{
public void M()
{
"A.M".Dump();
}
}
public class B : A
{
public new void M()
{
"B.M".Dump();
base.M();
}
}
Results:
B.M
A.M
Make M virtual in A
interface ISome
{
void M();
}
class B : ISome
{
public virtual M()
{
}
}
class A : B
{
public void override M()
{
base.M();
}
}
When you implement method M in class A, implement it as "virtual", then when you want to override it in class B use the "override" keyword, which will allow you to do just that.
interface I {
void M();
}
class A : I {
virtual void M() {
}
}
class B : A {
override void M() {
//Do stuff;
base.M();
}
}

How to access functions from abstract class without making them static?

I want to create a class that can only be inherited, for that i know it should be made abstract. But now the problem is that i want to use functions of that class without making them static. How can i do that.
public abstract Class A
{
A()
{}
public void display()
{}
}
public Class B:A
{
base.A() // this is accessible
this.display() // this is not accessible if i dont make this function static above
}
Your example will not compile, you could consider something like this:
using System;
public abstract class A
{
protected A()
{
Console.WriteLine("Constructor A() called");
}
public void Display()
{
Console.WriteLine("A.Display() called");
}
}
public class B:A
{
public void UseDisplay()
{
Display();
}
}
public class Program
{
static void Main()
{
B b = new B();
b.UseDisplay();
Console.ReadLine();
}
}
Output:
Constructor A() called
A.Display() called
Note: Creating a new B() implicitly calls A(); I had to make the constructor of A protected to prevent this error:
"'A.A()' is inaccessible due to its protection level"
That's not true. You don't have to make Display() static; you can call it freely from the subclass. On the other hand, you can't call the constructor like that.
Maybe it's just an error in the example, but the real issue with the code you have is that you can't put method calls in the middle of your class definition.
Try this:
public abstract class A
{
public void Display(){}
}
public class B:A
{
public void SomethingThatCallsDisplay()
{
Display();
}
}
Here's how you can do this..
public abstract class A
{
public virtual void display() { }
}
public class B : A
{
public override void display()
{
base.display();
}
public void someothermethod()
{
this.display();
}
}

Categories