Given the following classes structure, is there a way to prevent BaseMethod() from being called or seen from FinalClass?
public abstract class BaseClass
{
protected virtual void BaseMethod()
{
}
}
public class IntermediateClass : BaseClass
{
protected sealed override void BaseMethod()
{
base.BaseMethod();
}
private void IntermediateMethod()
{
BaseMethod();
}
}
public class FinalClass : IntermediateClass
{
protected void FinalMethod()
{
}
}
You could make BaseMethod internal and place FinalClass in a different assembly to BaseClass and IntermediateClass.
Related
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 {...}
I'm a new developer of c# and I'm using unity3d to develop a game.
I design an interface to implement the skill system in game. But I find some trouble. Here are a lot of Skill classes, and I must call show() method manually inside their apply.
interface ISkill
{
void apply();
}
class Base
{
protected string name { get; set; }
protected void show()
{
Console.WriteLine("show:"+name);
}
}
class Skill1 : Base, ISkill
{
public Skill1()
{
name = "skill1";
}
public void apply()
{
show();
Console.WriteLine("skill1 apply");
}
}
class Skill2 : Base, ISkill
{
public Skill2()
{
name = "skill2";
}
public void apply()
{
show();
Console.WriteLine("skill2 apply");
}
}
Skill3
Skill4
etc..
class Program
{
public static void Main(string[] args)
{
ISkill skill = new Skill2();
skill.apply();
}
}
How to modify my code so that the all SkillX classes can automatically call show() method in apply() method?
Standard solution for this is template method.
Base class implements method as "template" that forces derived classes to provide particular step(s) for that method. In your case the Base class should implement Apply method that calls Show first and than delegates the rest to derived classes by forcing them to provide implementation of the second part via abstract void ApplyImplementation():
interface ISkill
{
void Apply();
}
public abstract class Base
{
protected string name { get; set; }
protected Base(string name)
{
this.name = name;
}
protected void Show()
{
Console.WriteLine("show:"+name);
}
// "template" method.
public void Apply()
{
Show();
ApplyImplementation();
}
// derived class must implement that method
protected abstract void ApplyImplementation();
}
class Skill1 : Base, ISkill
{
public Skill1()
{
name = "skill1";
}
protected override void ApplyImplementation()
{
Console.WriteLine("skill1 apply");
}
}
No general solution, other than trying to pull the commonality across different classes to the base.
In your case, since the only differences among the apply() seems to be the skill name, and you already have it as an instance property, you can pull the apply up to the Base, and have the same implementation across all the child classes of Base.
interface ISkill
{
void apply();
}
class Base : ISkill
{
protected string name { get; set; }
protected Base(string name)
{
this.name = name;
}
public void apply()
{
show();
Console.WriteLine(name + " apply");
}
private void show()
{
Console.WriteLine("show:"+name);
}
}
class Skill1 : Base
{
public Skill1(): base("skill1"){}
}
class Skill2 : Base
{
public Skill2(): base("skill2"){}
}
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
}
}
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.
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 }