I have the below problem. Look my structure of code.
This will be ok if all my derived classes have the same sequence of methods in Process(Animal a). But imagine I have Turtle class, that extends Animal and when Process(Animal a) is called the methods inside have to be in different order and class Turtle has some extra methods for example Sleep.
What should I do in that case?
Thanks
public class Animal
{
public virtual string Eat(){ return "I'm eating"; }
public virtual string MakeNoise() { return "I'm ";}
public virtual string Go() { return "I'm walking"; }
}
public class Dog : Animal
{
public override string Eat()
{
return string.Format("{0} {1}",base.Eat(),"a pie");
}
public override string MakeNoise()
{
return string.Format("{0} {1}",base.MakeNoise(),"barking");
}
}
public class Controller
{
public void Process(Animal a)
{
a.Eat();
a.MakeNoise();
a.Go;
}
}
public class Client
{
IList<Animal> animals= new List<Animal>(){Dog,Cat,Turtle,Mouse}; //all animals have base class Animal
Controller = new Controller();
foreach(Animal a in animals)
{
p.Process(a);
}
}
You can add an overloaded method
public void Process(Turtle t)
{
//Do what you want here
}
You could write yourself a Controller factory that will return an appropriate controller for a given animal. Create a sub-class of Controller for Turtle, etc. Here I've assumed that we can extract an interface IControler, and IAnimal, but you could use abstract base types instead.
public class ControllerFactory
{
public static IController GetController (IAnimal animalToControl)
{
if (animalToControl is Turtle) { return new TurtleController(); }
if (animalToControl is Sheep) { return new SheepController(); }
// default
return new Controller();
}
}
and call with:
foreach(Animal a in animals)
{
var p = ControllerFactory.GetController(a);
p.Process(a);
}
The implementation of the factory here is crude, but illustrates the point.
Each animal has Eat, MakeNoise, and Go, but the sequence varies by animal (plus some additional behaviors for some animals.) Will the sequence always be the same for the given animal? Is the only reason why they inherit from Animal so that they can share the same base behaviors and only override when they need to?
If so then perhaps instead of a Process method in a controller there should be an ExecuteBehaviors method on the Animal which can be overridden by individual animals.
public virtual void ExecuteBehaviors()
{
Eat();
MakeNoise();
Go();
}
And then if an animal needs a different sequence it can override that method.
That seems to meet the description of your problem, to allow each animal to inherit behaviors but control their sequence and add new behaviors.
Then in your controller you can just call ExecuteBehavior for each animal. That's real polymorphism at work. You can treat any instance of Animal the same and call the same method on it whether it's a Dog or a Turtle, even though their behaviors will vary.
You have two options, the first one is extend the Process method. You can make a switch inside and define the order when a.GetType() == typeof(Turtle).
public class Controller
{
public void Process(Animal a)
{
if(a.GetType() == typeof(Turtle)
{
((Turtle)a).YourMethod();
}
else
{
a.Eat();
a.MakeNoise();
a.Go;
}
}
}
Or you can make the Animal class responsible for the Process method.
The idea here I think is not make Animal class responsible of Process method. That is where Controller come in action. Try to use a decorator pattern or a Factory for each Animal, as #Brett said
Related
I have some code that's equivalent to this (though this is a simplification):
namespace AnimalHospital
{
public class Animal { }
public class Dog : Animal { }
public class Cat : Animal { }
public interface Vet<T> where T : Animal
{
void takeCareOf(T animal);
}
public abstract class SpecializedDogVet<T> : Vet<T> where T : Dog
{
public abstract void takeCareOf(T dog);
}
public abstract class SpecializedCatVet<T> : Vet<T> where T : Cat
{
public abstract void takeCareOf(T cat);
}
public class AnimalHospital
{
public IList<SpecializedCatVet<Cat>> CatVets = new List<SpecializedCatVet<Cat>>();
public IList<SpecializedDogVet<Dog>> DogVets = new List<SpecializedDogVet<Dog>>();
private void treatSickAnimal(IEnumerable<Vet<Animal>> vets, Animal patient)
{
foreach(var vet in vets)
{
vet.takeCareOf(patient);
}
}
public void treatSickCat(Cat cat)
{
treatSickAnimal(CatVets, cat);
}
public void treatSickDog(Dog dog)
{
treatSickAnimal(DogVets, dog);
}
}
}
I get an error, telling me that conversion from:
IList<SpecializedCatVet<Cat>> to IEnumerable<Vet<Animal>> is not possible. How can this be? Before this they were nonegeneric, and i had some other problems, as i could not override the vet interfaces takeCareOf method. I had expected that as IEnumerable of Animal can easily be instantiated with a list of Dog, the same would be the case with parsing a collection of generics as long as their type parameter is a derirative of the required type. This is not the case though, and I seem unable to figure out why, or how to do this properly.
Thanks for reading.
UPDATE: I'm Accepting JLRishe's answer, makes perfect sense. Thank you very much.
This is not allowed, because if it were allowed, you could something like this:
var cat = new Cat();
treatSickAnimal(DogVets, cat);
And essentially try to force dog vets to treat a cat.
You can remedy this by making your methods generic on the animal parameter:
private void treatSickAnimal<T>(IEnumerable<Vet<T>> vets, T patient) where T : Animal
{
foreach (var vet in vets)
{
vet.takeCareOf(patient);
}
}
This should allow your code to compile correctly and ensure that you don't try to force any dog vets to treat cats.
Side note note - unless you plan on having specialized types (subclasses) of Dog and Cat and vets that are specialized for those subclasses, you can simplify the definition of SpecializedDogVet and SpecializedCatVet to be like this:
public abstract class SpecializedDogVet : Vet<Dog>
{
public abstract void takeCareOf(Dog dog);
}
public abstract class SpecializedCatVet : Vet<Cat>
{
public abstract void takeCareOf(Cat cat);
}
You would then refer to the types like this:
public IList<SpecializedCatVet> CatVets = new List<SpecializedCatVet>();
public IList<SpecializedDogVet> DogVets = new List<SpecializedDogVet>();
You cant because your Vet<T> interface is currently invariant, notice you can make it contravariant by specifying that it is input parameter like so:
public interface Vet<in T> where T : Animal
{
void takeCareOf(T animal);
}
This is possible because everywhere T is used as input parameter.
In order your code to compile you can do what #JLRishe said, or you can change your logic and make T output parameter, but in order to do that you need to change your Vet implementation so everywhere T is used it needs to be in position of output just an example:
public interface Vet<out T> where T : Animal
{
T takeCareOf();
}
So in conclusion, you can pass base class to interfaces or delegates where they have type parameters defined as output and you can pass more derived classes when type parameters are defined as input.
This is actually AMAZING article for covariance and contravariance if I got you hooked you should definitely check it http://tomasp.net/blog/variance-explained.aspx/
I am trying to understand the logic behind some C# casting conditions for classes, This is my testing code
File: example.cs
public class Animal { public string animal_name = "Animal"; }
public class Dog : Animal { public string dog_name = "Dog"; }
public class Class1
{
public void createObjects()
{
var animal1 = new Animal();
printAnimalName(animal1);
}
public void printAnimalName(Animal my_animal)
{
var dog1 = my_animal as Dog; // dog1 is of type Dog
Console.WriteLine(dog1.dog_name);
}
}
In my Main function, I call the call createObjects function as follows:
static void Main(string[] args)
{
Class1 c1 = new Class1();
c1.createObjects();
Console.ReadLine();
}
Running the code above gives an error
System.NullReferenceException:'Object reference not set to an instance of an object'
I understand that this is the way it should be, due to the casting in:
var dog1 = my_animal as Dog;
But what is the logic behind it? Why can't we call the function printAnimalName by passing an Animal object for it? This should be possible as per my understanding, because the function expects an Animal object.
After that var dog1 = my_animal as Dog; // dog1 is of type Dog you need to add only null check:
if(dog1 != null)
{
Console.WriteLine(dog1.dog_name);
}
I think you need to learn about polymorphism, abscract classes and interfaces.
public abstract class FourLeggedAnimal
{
public int GetLegCount()
{
return 4;
}
}
public class Dog : FourLeggedAnimal
{
public string GetScientificName()
{
return "doggus scientificus";
}
}
public class Cat : FourLeggedAnimal
{
public string GetServant()
{
return "human";
}
}
public class AnimalInformer
{
public void DisplayInformation(FourLeggedAnimal animal)
{
Console.WriteLine("It has {0} legs", animal.GetLegCount());
if (animal is Dog)
Console.WriteLine("Its scientific name is {0}", ((Dog)animal).GetScientificName());
if (animal is Cat)
Console.WriteLine("Its servant is {0}", ((Cat)animal).GetServant());
}
}
Here you use the absract class to provide base functionality to all other classes derived from it. All classes derived from FourLeggedAnimal have a method GetLegCount() that returns the number of legs.
But a cat has a servant a dog doesnt have, it just has a friend(both humans, but different relations). So the dog needs no method "GetServant" but the cat does. -> Differenct implementations in 2 seperate classes
Another example with interfaces is that each derived class needs to provide that functionality.
public interface IMovableObject
{
int GetMaxSpeed();
}
public class Car : IMovableObject
{
public int GetMaxSpeed()
{
return 100;
}
}
public class Human : IMovableObject
{
public int GetMaxSpeed()
{
return 20;
}
}
public static class SpeedChecker
{
public static void CheckSpeed(IMovableObject speedster)
{
Console.WriteLine("Checking Speed..");
int speed = speedster.GetMaxSpeed();
if (speed > 50)
Console.WriteLine("It's really fast!");
else
Console.WriteLine("Just a turtle or something similar...");
}
}
Now, if you have a Method getting a IMovableObject that is actually a car, you call the implementation of Car:
Car c = new Car();
Human h = new Human();
Console.WriteLine("Checking Car..");
SpeedChecker.CheckSpeed(c);
Console.WriteLine("Checking Human..");
SpeedChecker.CheckSpeed(h);
-> returns:
Checking Car...
Checking Speed...
It's really fast!
Checking Human...
Checking Speed...
Just a turtle or something similar...
These are 2 uses where you derive classes and use castings to get certain functionality or use the basetype without casting but still getting different functionality
Your problem is here:
public void printAnimalName(Animal my_animal)
{
var dog1 = my_animal as Dog; // dog1 is of type Dog
Console.WriteLine(dog1.dog_name); //Animal does not have this property!
}
Casting does not invoke a constructor. This means that dog_name is null, as my_animal does not have a dog_name property. I think you missed something on inheritance here.
This is actually an example that happens in more complex form in the real world; Given class A, B inherits from A. Both have the same properties because of inheritance. Then someone makes a different property with a similar, but not congruous property name and uses it for the same function in the child object. Welcome to code smell city.
To fix your function so it comes across as a dog, you'd do two things:
public class Animal { public string animal_name = "Animal"; }
//since we want a different default, we can
//can make the change in the constructor
public class Dog : Animal
{
Dog(){ this.animal_name = "Dog"; }
//if you really, really want a second name string, you can do this:
public string Dog_Name
{
get { return this.animal_name; }
set { this.animal_name = value; }
}
}
Then, you need to make your method call the appropriate property.
public void printAnimalName(Animal my_animal)
{
var dog1 = my_animal as Dog; // dog1 is of type Dog
Console.WriteLine(dog1.animal_name);
}
I also recommend changing your public fields to properties and possibly override ToString() when all you want to do with an object is return a string representing it.
Consider the following classes :
public abstract class Animal
{
public abstract Animal GiveBirth();
}
public class Monkey : Animal
{
public override Animal GiveBirth()
{
return new Monkey();
}
}
public class Snake : Animal
{
public override Animal GiveBirth()
{
return new Snake();
}
}
//That one doesnt makes sense.
public class WeirdHuman: Animal
{
public override Animal GiveBirth()
{
return new Monkey();
}
}
I'm searching a way to enforce the return types of the overrided GiveBirth method so that it always returns the actual class type, so that no WeirdHuman can give birth to a Monkey.
I feel like the answer is about generic types, but I can't see how I can do that.
Exemple of the expected result :
public abstract class Animal
{
public abstract /*here a way to specify concrete type*/ GiveBirth();
}
public class Monkey : Animal
{
public override Monkey GiveBirth() //Must returns an actual Monkey
{
return new Monkey();
}
}
"Absolutely impossible" may be an answer, if clearly explained.
This is co-variant returns and is not supported by C#. I lament this daily. The best you can hope to do to get around it is to use a generic return type and specify a where condition on the generic type, but this can also cause you to run in to other issues down the road with matching generic parameter requirements.
public abstract class Animal<TBirthType> where TBirthType : Animal<TBirthType>
{
public abstract TBirthType GiveBirth();
}
public class Monkey<TBirthType> : Animal<TBirthType> where TBirthType : Monkey<TBirthType>
{
public override TBirthType GiveBirth()
{
return new Monkey<Monkey>();
}
}
Alternately, if you don't need any further inheritance, you can close the generic.
public class Monkey : Animal<Monkey>
{
public override Monkey GiveBirth()
{
return new Monkey();
}
}
Note that covariance alone is still not enough to ensure that no misbehaving derived type can be formed, but it will allow for the type of the return to be specified as the type being used. There still wouldn't be a way to lock it down from the abstract class though. You could perhaps manage a runtime check via reflection from a method implemented at the base level that would check type at runtime, but this could also be very messy.
As far as I know, there is no clean way to support this purely in a single class hierarchy. Using recurring generic type parameters e.g.
public class Animal<T> where T : Animal<T> { }
may be acceptable if you control the entire hierarchy, and can therefore rule out classes like
public class WierdHuman<Monkey> { }
What you really want is something like Haskell's typeclasses, where you can abstract over the concrete type of the class itself. The closest you can get in C# is to define a surrogate object which implements the required functionality, and then pass that around wherever you require it.
In your case, this means creating an interface for giving birth, and implementing it for each concrete animal type.
Your methods which require this functionality then need an extra parameter for the 'typeclass instance'. These methods can restrict the generic animal type to be the same:
public interface ISpawn<T> where T : Animal
{
public T GiveBirth();
}
public void Populate<T>(T parent, ISpawn<T> spawn) where T : Animal
{
}
You can do something like this, which forces the implementers of Animal<T> to implement an Animal<T> GiveBirth() method which returns the same type as the type parameter, which itself is constrained to be a kind of animal.
That's not quite what you want, but just so you can see:
public abstract class Animal<T> where T: Animal<T>
{
public abstract Animal<T> GiveBirth();
}
public class Monkey: Animal<Monkey>
{
public override Animal<Monkey> GiveBirth()
{
return new Monkey();
}
}
public class Snake: Animal<Snake>
{
public override Animal<Snake> GiveBirth()
{
return new Snake();
}
}
public class WeirdHuman: Animal<WeirdHuman>
{
public override Animal<WeirdHuman> GiveBirth()
{
return new Monkey(); // Won't compile of course.
}
}
If you comment out the public override Animal<Monkey> GiveBirth() methods, you'll see that the compiler complains and says something like:
Error 1 'ConsoleApplication1.Monkey' does not implement inherited abstract member 'ConsoleApplication1.Animal.GiveBirth()'
Unfortunately, you must declare the classes using the SomeKindOfAnimal: Animal<SomeKindOfAnimal> syntax, but maybe this will work for you.
(Also see this thread.)
Alas, this doesn't quite work because it allows you to do this:
public class Monkey: Animal<WeirdHuman>
{
public override Animal<WeirdHuman> GiveBirth()
{
return new WeirdHuman();
}
}
In other words, it constrains the type parameter to be a kind of animal, and it also constrains the return type of GiveBirth() to be the same as the type parameter; but that's all it does. In some cases this is enough, but probably not for your purposes.
Still, perhaps this approach is worth knowing about.
If you have an situation where your base class cannot be generic for various reasons, this method might be useful:
abstract class Animal {
}
interface ICanGiveBirth<T> {
T GiveBirth();
}
static class CanGiveBirthHelper {
public static T GiveBirth<T>(this T v) where T: ICanGiveBirth<T> => v.GiveBirth();
}
class Monkey : Animal, ICanGiveBirth<Monkey> {
public Monkey GiveBirth() {
throw new NotImplementedException();
}
}
class Snake : Animal, ICanGiveBirth<Snake> {
public Snake GiveBirth() {
throw new NotImplementedException();
}
}
If you are unable to add interface to your sub classes, and still unable to add generics to the Base type this method might be useful:
(Unfortunately you cannot make the GiveBirthImpl protected, since the helper class is not allowed to be inside the base class)
abstract class Animal {
public abstract T GiveBirthImpl<T>() where T:Animal;
}
static class CanGiveBirthHelper {
public static T GiveBirth<T>(this T v) where T: Animal => v.GiveBirthImpl<T>();
}
class Monkey : Animal {
public override T GiveBirthImpl<T>() {
throw new NotImplementedException();
}
}
class Snake : Animal {
public override T GiveBirthImpl<T>() {
throw new NotImplementedException();
}
}
In both cases, this will work as expected:
class Tester
{
Monkey TestIt() => new Monkey().GiveBirth();
}
I understand that static method inheritance is not supported in C#. I have also read a number of discussions (including here) in which developers claim a need for this functionality, to which the typical response is "if you need static member inheritance, there's a flaw in your design".
OK, given that OOP doesn't want me to even think about static inheritance, I must conclude that my apparent need for it points to an error in my design. But, I'm stuck. I would really appreciate some help resolving this. Here's the challenge ...
I want to create an abstract base class (let's call it a Fruit) that encapsulates some complex initialization code. This code cannot be placed in the constructor, since some of it will rely on virtual method calls.
Fruit will be inherited by other concrete classes (Apple, Orange), each of which must expose a standard factory method CreateInstance() to create and initialize an instance.
If static member inheritance were feasible, I would place the factory method in the base class and use a virtual method call to the derived class to obtain the type from which a concrete instance must be initialized. The client code would simple invoke Apple.CreateInstance() to obtain a fully initialized Apple instance.
But clearly this is not possible, so can someone please explain how my design needs to change to accommodate the same functionality.
One idea:
public abstract class Fruit<T>
where T : Fruit<T>, new()
{
public static T CreateInstance()
{
T newFruit = new T();
newFruit.Initialize(); // Calls Apple.Initialize
return newFruit;
}
protected abstract void Initialize();
}
public class Apple : Fruit<Apple>
{
protected override void Initialize() { ... }
}
And call like so:
Apple myAppleVar = Fruit<Apple>.CreateInstance();
No extra factory classes needed.
Move the factory method out of the type, and put it in its own Factory class.
public abstract class Fruit
{
protected Fruit() {}
public abstract string Define();
}
public class Apple : Fruit
{
public Apple() {}
public override string Define()
{
return "Apple";
}
}
public class Orange : Fruit
{
public Orange() {}
public override string Define()
{
return "Orange";
}
}
public static class FruitFactory<T>
{
public static T CreateFruit<T>() where T : Fruit, new()
{
return new T();
}
}
But, as I'm looking at this, there is no need to move the Create method to its own Factory class (although I think that it is preferrable -separation of concerns-), you can put it in the Fruit class:
public abstract class Fruit
{
public abstract string Define();
public static T CreateFruit<T>() where T : Fruit, new()
{
return new T();
}
}
And, to see if it works:
class Program
{
static void Main( string[] args )
{
Console.WriteLine (Fruit.CreateFruit<Apple> ().Define ());
Console.WriteLine (Fruit.CreateFruit<Orange> ().Define ());
Console.ReadLine ();
}
}
I would do something like this
public abstract class Fruit() {
public abstract void Initialize();
}
public class Apple() : Fruit {
public override void Initialize() {
}
}
public class FruitFactory<T> where T : Fruit, new {
public static <T> CreateInstance<T>() {
T fruit = new T();
fruit.Initialize();
return fruit;
}
}
var fruit = FruitFactory<Apple>.CreateInstance()
Why not create a factory class (templated) with a create method?
FruitFactory<Banana>.Create();
The WebRequest class and its derivative types in the .NET BCL represent a good example of how this sort of design can be implemented relatively well.
The WebRequest class has several sub-classes, including HttpWebRequest and FtpWebReuest. Now, this WebRequest base class is also a factory type, and exposes a static Create method (the instance constructors are hidden, as required by the factory pattern).
public static WebRequest Create(string requestUriString)
public static WebRequest Create(Uri requestUri)
This Create method returns a specific implementation of the WebRequest class, and uses the URI (or URI string) to determine the type of object to create and return.
This has the end result of the following usage pattern:
var httpRequest = (HttpWebRequest)WebRequest.Create("http://stackoverflow.com/");
// or equivalently
var httpRequest = (HttpWebRequest)HttpWebWebRequest.Create("http://stackoverflow.com/");
var ftpRequest = (FtpWebRequest)WebRequest.Create("ftp://stackoverflow.com/");
// or equivalently
var ftpRequest = (FtpWebRequest)FtpWebWebRequest.Create("ftp://stackoverflow.com/");
I personally think this is a good way to approach the issue, and it does indeed seem to be the preffered method of the .NET Framework creators.
First of all, not having static initializers that can be virtual doesn't mean you can't have "standard" member methods, that could be overloaded. Second of all, you can call your virtual methods from constructors, and they will work as expected, so there's no problem here. Third of all, You can use generics to have type-safe factory.
Here's some code, that uses factory + member Initialize() method that is called by constructor (and it's protected, so you don't have to worry, that someone will call it again after creating an object):
abstract class Fruit
{
public Fruit()
{
Initialize();
}
protected virtual void Initialize()
{
Console.WriteLine("Fruit.Initialize");
}
}
class Apple : Fruit
{
public Apple()
: base()
{ }
protected override void Initialize()
{
base.Initialize();
Console.WriteLine("Apple.Initialize");
}
public override string ToString()
{
return "Apple";
}
}
class Orange : Fruit
{
public Orange()
: base()
{ }
protected override void Initialize()
{
base.Initialize();
Console.WriteLine("Orange.Initialize");
}
public override string ToString()
{
return "Orange";
}
}
class FruitFactory
{
public static T CreateFruit<T>() where T : Fruit, new()
{
return new T();
}
}
public class Program
{
static void Main()
{
Apple apple = FruitFactory.CreateFruit<Apple>();
Console.WriteLine(apple.ToString());
Orange orange = new Orange();
Console.WriteLine(orange.ToString());
Fruit appleFruit = FruitFactory.CreateFruit<Apple>();
Console.WriteLine(appleFruit.ToString());
}
}
I'd say the best thing to do is to create a virtual/abstract Initialise method on the fruit class which must be called and then create an external 'fruit factory' class to create instances:
public class Fruit
{
//other members...
public abstract void Initialise();
}
public class FruitFactory()
{
public Fruit CreateInstance()
{
Fruit f = //decide which fruit to create
f.Initialise();
return f;
}
}
All these ideas compensate for a glaring lack of language with stilted language constructs.
If I want an apple, I don't call a method on the fruit. Why should I even learn the family tree of the class? And I don't want to repeat myself or copy constructors through the whole hierarchy like a madman. Computers were invented to save me from such nonsense.
Two languages that have noticed and are now doing it right are PHP and Swift. Both supported static inheritance and covariance.
And old holy OOP books with a supposedly pure doctrine you can burn, because everything that allows me elegant code and compiles is good.
I have a c# Class that has lots of virtual methods, some of these methods are essentially abstract ( they are fully implemented in subclasses and the base class is empty).
To get it to compile i am throwing an InvalidOperationException in the base class with a comment on what should be done. This just feels dirty.
Is there a better way to design my classes?
edit:
It is for the middle tier of an application that will be ran in canada, half of the methods are generic hence the virtual. and half of the methods are province specific.
Public class PersonComponent()
{
public GetPersonById(Guid id) {
//Code to get person - same for all provinces
}
Public virtual DeletePerson(Guid id) {
//Common code
}
Public virtual UpdatePerson(Person p) {
throw new InvalidOperation("I wanna be abstract");
}
Public Class ABPersonComponent : PersonComponent
{
public override DeletePerson(Guid id)
{
//alberta specific delete code
}
public override UpdatePerson(Person p)
{
//alberta specific update codecode
}
}
hope this makes sense
Mark the base class as abstract, as well as the methods that have no implementation.
Like so
public abstract class BaseClass
{
public abstract void AbstractMethod();
}
public class SubClass: BaseClass
{
public override void AbstractMethod()
{
//Do Something
}
}
You can't have abstract methods outside of an abstract class. Marking a class as abstract means you won't be able to instantiate it. But then it doesn't make any sense to. What are you going to do with a class that doesn't implement the methods anyway?
Edit: From looking at your class, yeah I'd make PersonComponent abstract along with the UpdatePerson method. Either that, or if UpdatePerson just doesn't do anything for a PersonComponent keep it as is, but make the UpdatePerson method empty for PersonComponent.
Think about your object hierarchy. Do you want to share common code for all your derived classes, then implement base functionality in the base class.
When having shared base code, please notice the Template pattern. Use a public method and chain it to a protected virtual method with the core/shared implementation. End the shared implementation methodname with "Core".
For example:
public abstract class BaseClass
{
protected virtual void DeletePersonCore(Guid id)
{
//shared code
}
public void DeletePerson(Guid id)
{
//chain it to the core
DeletePersonCore(id);
}
}
public class DerivedClass : BaseClass
{
protected override void DeletePersonCore(Guid id)
{
//do some polymorphistic stuff
base.DeletePersonCore(id);
}
}
public class UsageClass
{
public void Delete()
{
DerivedClass dc = new DerivedClass();
dc.DeletePerson(Guid.NewGuid());
}
}