Avoiding the call to protected member of base class - c#

Here's a silly example of a tree structure where every node does a different kind of an action, but exactly one node (any node) has to do some common work at the start and end of a project.
public abstract class Employee
{
public void StartProject()
{
AnnounceProjectToNewspapers();
DoActualWork();
PutProductOnMarket();
}
protected abstract void DoActualWork();
private void AnnounceProjectToNewspapers() { }
private void PutProductOnMarket() { }
}
public class Engineer : Employee
{
protected override void DoActualWork()
{
// Build things.
}
}
public class Salesman : Employee
{
protected override void DoActualWork()
{
// Design leaflets.
}
}
public class Manager : Employee
{
protected override void DoActualWork()
{
// Make gantt charts.
// Also delegate.
foreach (var subordinate in subordinates)
// ...but then compiler stops you.
subordinate.DoActualWork();
}
private List<Employee> subordinates;
}
The problem is, you can't call the protected method DoActualWork() on a base class.
Two solutions I see are:
Make DoActualWork() public. But this would allow anyone to call it without AnnounceProjectToNewspapers() or PutProductOnmarket().
Make DoActualWork() internal. But this would prevent other assemblies from using the "management system".
Is there a standard work-around people use to avoid this limitation?

I have a couple of ways to achieve what you need.
The first and obvious way is to inherit Engineer and Salesman from Manager instead of employee. But this makes the inheritance sound ridiculous. Every Engineer is a Manager (I wish that was true.)
As you've mentioned,
Make DoActualWork() public
This does work. To then prevent any other method from calling DoActualWork() you could find out the type of the class using reflection/stacktrace and block invalid types. Refer here
But both these methods feel clanky to me. There should definitely be a way to design the classes to get what you need.

I came up with a solution like this (this has not been tested)
public interface IEmployee {
void StartProject();
void DoWork();
}
public abstract class EmployeeBase : IEmployee {
public void StartProject() {
AnnounceProjectToNewspapers();
DoActualWork();
PutProductOnMarket();
}
void IEmployee.DoWork() {
// Maybe set a flag to see whether the work has been already done by calling StartProject().
this.DoActualWork();
}
protected abstract void DoActualWork();
private void AnnounceProjectToNewspapers() { }
private void PutProductOnMarket() { }
}
public class Employee : EmployeeBase {
protected override void DoActualWork() {
// Log system Action
}
}
public class Engineer : Employee {
protected override void DoActualWork() {
// Build things.
}
}
public class Salesman : Employee {
protected override void DoActualWork() {
// Design leaflets.
}
}
public class Manager : Employee {
protected override void DoActualWork() {
DoWorkInternal();
}
private void DoWorkInternal() {
foreach (var subordinate in subordinates)
subordinate.DoWork();
}
private List<IEmployee> subordinates;
}

Thinking about all the responses, a compromise just crossed my mind: use an indirect call through an internal method. In other words, a poor man's friend declaration by informal comments.
Here are the relevant bits:
public abstract class Employee
{
// Meant to be called by Manager class only.
internal void FollowTheLeader()
{
DoActualWork();
}
}
public class Manager : Employee
{
protected override void DoActualWork()
{
// Make gantt charts.
// Also delegate.
foreach (var subordinate in subordinates)
// ...but then compiler stops you.
subordinate.FollowTheLeader();
}
}
Deriving classes from other assemblies will be able to customize the work Employees and Managers do, but they will not be able to make anyone do work without proper context.
Classes from within the assembly will be able to do anything, but let's assume you can trust the people developing the framework to follow the instructions in comments.

Related

Pass-through constructors from its base class

An external framework has the following classes:
public class Boatmaker
{
}
public class Wood
{
}
public class Axe
{
}
public class Lake
{
}
public class Boat
{
public Boat(Wood wood, Axe axe) {
}
public Boat (Boatmaker maker) {
}
public Boat (Lake lake) {}
}
I need to do a lot of subclassing of Boat. For each of my subclasses, I have to assume that the external framework may want to instantiate it via any of the above constructors. So my subclasses get pass-through constructors. Notice how they never go away:
public class SmallBoat: Boat
{
public void DoSmallBoatStuff() {
// some code here
}
private void Initialize() {
this.DoSmallBoatStuff();
}
public SmallBoat(Wood wood, Axe axe): base(wood, axe) {
this.Initialize();
}
public SmallBoat (Boatmaker maker): base(maker) {
this.Initialize();
}
public SmallBoat (Lake lake): base(lake) {
this.Initialize();
}
}
public class Canoe: SmallBoat
{
public void DoCanoeStuff() {
// some code here
}
private void Initialize() {
this.DoCanoeStuff();
}
public Canoe(Wood wood, Axe axe): base(wood, axe) {
this.Initialize();
}
public Canoe (Boatmaker maker): base(maker) {
this.Initialize();
}
public Canoe(Lake lake): base(lake) {
this.Initialize();
}
}
I am wondering if there is a way to simplify the appearance of the code. The only difference between the way the constructors are written in SmallBoat and Canoe is the word SmallBoat or Canoe. Everything else is the same.
So if there were a way to write a constructor without actually using the name of the class in the constructor, it would help a lot. I could use direct copy and paste without a .tt file (which is not really viable for me -- most of my work is not done in Visual Studio). Is there a way to do that?
No. There is not. You have to specify which constructors of the base class you want to make available from the current class. There is no way to write the constructor without mentioning the real class name.
It might be a simplification you are showing, but if Initialize is the only method called, you might want to move that call to the base class calling a protected Initialize method you can override from the implementing classes. (You have to take in consideration the order of calling that method and instantiating properties/fields. You can run into trouble there, so it might not be viable in your situation)
1. Automation of code typing
There is code snippet : ctor that helps create "only" default constructor.
To use it type ctor an tabulation twice.
The original code snippet can be copied to create your own.
In Visual Studio, go in Tools menu/Code snippet manager.
You can see here the directories of the snippet files.
You can copy a snippet ( ctor.snippet for instance ) to "My Code Snippets", rename it and edit.
2. Design of the boat hierarchy
The boat hierarchy can also be designed so there is only a default constructor in the base class, and you have public properties or public method(s) in the base class to provide Lake, Axe, BoatMaker, ...
If you can change the design, I highly recommend separate object instantiation from the object itself. This way, the Factory Method combining with Template Method design pattern comes very helpful:
public abstract class BoatFactory
{ protected abstract void Initialize();
protected Wood Wood;
protected Axe Axe
protected Boatmaker Boatmaker ;
public Boat MakeBoat(Wood wood, Axe axe)
{
this.Wood = wood;
this.Axe = axe;
Initialize();
}
public Boat MakeBoat(Boatmaker maker)
{
this.Boatmaker = Boatmaker ;
Initialize();
}
public Boat MakeBoat(Lake lake)
{
this.Lake = lake;
Initialize();
}
}
public class SmallBoatFactory : BoatFactory
{
protected override void Initialize()
{
// do customized init operations here
}
}

How do I call the top ancestor method [duplicate]

class GrandParent
{
public virtual void Foo() { ... }
}
class Parent : GrandParent
{
public override void Foo()
{
base.Foo();
//Do additional work
}
}
class Child : Parent
{
public override void Foo()
{
//How to skip Parent.Foo and just get to the GrandParent.Foo base?
//Do additional work
}
}
As the code above shows, how can I have the Child.Foo() make a call into GrandParent.Foo() instead of going into Parent.Foo()? base.Foo() takes me to the Parent class first.
Your design is wrong if you need this.
Instead, put the per-class logic in DoFoo and don't call base.DoFoo when you don't need to.
class GrandParent
{
public void Foo()
{
// base logic that should always run here:
// ...
this.DoFoo(); // call derived logic
}
protected virtual void DoFoo() { }
}
class Parent : GrandParent
{
protected override void DoFoo()
{
// Do additional work (no need to call base.DoFoo)
}
}
class Child : Parent
{
protected override void DoFoo()
{
// Do additional work (no need to call base.DoFoo)
}
}
I think there is something wrong with your design here. Essentially, you want to "break" the rules of polymorphism. You are saying Child should derive from Parent but want to conveniently skip the implementation in it's parent.
Re-think your design.
No. It wouldn't be reliable anyway. You, as the implementer of your class, get to choose your immediate base class. But who is to say that a later release of Parent might not inherit from ParentBase, that in turn inherits from GrandParent? So long as Parent is still implementing the correct contract, this should not cause any issues for those classes inheriting from Parent.
No, this isn't possible. Imagine how crazy things would be if this was possible.
If you want something specific skipped in the Child case, consider reworking your design to better represent what you need (e.g. maybe you need to override something else in the Child class, too). Or, you could provide another Foo() in the Parent class that doesn't do anything except call its base.Foo().
If you have control of the code, the simplest way is to create a protected method in Parent class that only call base.Foo() and your child class Foo implementation call that method explicitly
We had exactly this scenario on a large project where the derived methods were called from various locations. Due to change management and QA scripts not to be broken, among other constraints, "drastic" refactoring and class re-structuring are not always possible on a large mature project. Also we did not want to override the method and exclude all base functionality. Most solutions seen elsewhere, looked a bit clumsy, but the solution from Josh Jordan on How to call base.base was quite useful.
However we followed the approach below (which I see now is very similar to what Dan Abramov propose).
public class Base
{
public virtual void Foo()
{
Console.WriteLine("Hello from Base");
}
}
public class Derived : Base
{
public override void Foo()
{
base.Foo();
Console.WriteLine("Text 1");
WriteText2Func();
Console.WriteLine("Text 3");
}
protected virtual void WriteText2Func()
{
Console.WriteLine("Text 2");
}
}
public class Special : Derived
{
public override void WriteText2Func()
{
//WriteText2Func will write nothing when method Foo is called from class Special.
//Also it can be modified to do something else.
}
}
All these strong opinions...
Sometimes it just makes sense to use 99% of something...
public class Base
{
public virtual void Foo()
{
// Do something
}
}
public class DerivedLevel1 : Base
{
public override void Foo()
{
DerivedLevel1Foo();
}
protected void DerivedLevel1Foo()
{
// Do something
base.Foo();
}
}
public class DerivedLevel2 : DerivedLevel1
{
public override void Foo()
{
DerivedLevel2Foo();
}
protected void DerviedLevel2Foo()
{
// Do something
base.Foo();
}
}
public class Special : Derived
{
public override void Foo()
{
// Don't do DerivedLevel2Foo()
base.DerivedLevel1Foo();
}
}

Call abstract method from abstract class constructor

I would like to ask what are the risks of having something as follows:
abstract public class HtmlTemplateBuilder
{
HtmlSource source;
protected HtmlTemplateBuilder()
{
LoadTemplates();
}
public abstract void LoadTemplates();
}
The risk is if a derived class derives from the derived class:
DerivedClass2 -> #DerivedClass1 -> HtmlTemplateBuilder
This can be solved by sealing #DerviedClass1, but are there any more risks or better practices for implementing this functionality?
Thanks
The situation in which this pattern bit me is as follows: at some later stage you want to add a specialized HtmlTemplateBuilder, which can load different templates based on some criteria unknown to the class itself (maybe you decide you want some cool templates on a specific day of the year). That is:
public class SpecialHtmlTemplateBuilder : HtmlTemplateBuilder
{
private bool someCondition;
public override void LoadTemplates()
{
if (someCondition)
{
LoadTemplatesSet1();
}
else
{
LoadTemplatesSet2();
}
}
}
But how are you going to pass someCondition to the class? The following won't work:
public class SpecialHtmlTemplateBuilder : HtmlTemplateBuilder
{
private bool someCondition;
public SpecialHtmlTemplateBuilder (bool someCondition)
{
this.someCondition = someCondition;
}
// ...
}
because the assignment of this.someCondition will be done after calling the base constructor, i.e., after LoadTemplates() is called. Note that sealing derived classes does not solve this problem.
The way to solve this is as #Rahul Misra described: add an explicit Initialize method and call that after the constructor.
Have a look at this link which explains the perils with simple easy to understand examples
https://blogs.msmvps.com/peterritchie/2012/04/25/virtual-method-call-from-constructor-what-could-go-wrong/
I would remove the call to LoadTemplates from constructor and call Initialise on it when the templates actually need to be loaded and used.
abstract public class HtmlTemplateBuilder
{
HtmlSource source;
object locker = new object();
private bool initialised;
protected HtmlTemplateBuilder()
{
}
protected void Initialise()
{
lock (locker)
{
if(initialised)
{
LoadTemplates();
initialised = true;
}
}
}
public abstract void LoadTemplates();
}

Require child classes to call super.doSomething() if overrides it?

I have a abstract class named Vehicle:
public abstract class Vehicle {
public void run() {
addToRunningVehicleList();
}
}
I want that every classes that extends Vehicle must call super.run() if they override run method. For example:
public class Car {
#Override
public void run() { // Error here because does not call super.run()
carRunningAnimation();
}
}
Is it possible in OOP concept, or Java/C#?
EDIT: Following Petar Ivanov, I have this code:
public abstract class Vehicle {
public final void run() {
Log.e("Run", "Add To List");
runImp();
}
public void runImp() {}
}
public class Car extends Vehicle {
#Override
public void runImp() {
Log.e("Run", "Run in Car");
}
}
However, it's not very good for public APIs. When extending Vehicle, the end-users must override runImp, but then they have to call run() method, so I have to make public both run and runImp, which make nothing better.
Here is how I would do it (C#):
public abstract class Vehicle {
public void Run() {
//code that will always run
addToRunningVehicleList();
//code that can be overriden
RunImpl();
}
protected virtual void RunImpl() { }
}
public class Car : Vehicle {
protected override void RunImpl() {
carRunningAnimation();
}
}
You can make the RunImpl protected to make sure it can't be called outside the subclasses of Vehicle.
If you need to require certain code to run in addition to the child class' implementation, perhaps you need to split this into multiple methods:
(C# example)
public abstract class Vehicle
{
public void Run()
{
// Code that always runs before...
RunCore();
// Code that always runs after...
}
protected virtual void RunCore()
{
}
}
Remember who you are designing for. If it's an internal piece of code a comment will suffice. If it's a public API and you want people to inherit then you need to write a piece of documentation telling them to do it.
In C# you can do some sneaky stuff with virtual and non-virtual methods but in Java as all inheritence is virtual it's a lot harder to enforce this without using an abstract base class.
Using an ABT may limit your ability to provide further inheritence and force modification of other code.

C#: Any way to skip over one of the base calls in polymorphism?

class GrandParent
{
public virtual void Foo() { ... }
}
class Parent : GrandParent
{
public override void Foo()
{
base.Foo();
//Do additional work
}
}
class Child : Parent
{
public override void Foo()
{
//How to skip Parent.Foo and just get to the GrandParent.Foo base?
//Do additional work
}
}
As the code above shows, how can I have the Child.Foo() make a call into GrandParent.Foo() instead of going into Parent.Foo()? base.Foo() takes me to the Parent class first.
Your design is wrong if you need this.
Instead, put the per-class logic in DoFoo and don't call base.DoFoo when you don't need to.
class GrandParent
{
public void Foo()
{
// base logic that should always run here:
// ...
this.DoFoo(); // call derived logic
}
protected virtual void DoFoo() { }
}
class Parent : GrandParent
{
protected override void DoFoo()
{
// Do additional work (no need to call base.DoFoo)
}
}
class Child : Parent
{
protected override void DoFoo()
{
// Do additional work (no need to call base.DoFoo)
}
}
I think there is something wrong with your design here. Essentially, you want to "break" the rules of polymorphism. You are saying Child should derive from Parent but want to conveniently skip the implementation in it's parent.
Re-think your design.
No. It wouldn't be reliable anyway. You, as the implementer of your class, get to choose your immediate base class. But who is to say that a later release of Parent might not inherit from ParentBase, that in turn inherits from GrandParent? So long as Parent is still implementing the correct contract, this should not cause any issues for those classes inheriting from Parent.
No, this isn't possible. Imagine how crazy things would be if this was possible.
If you want something specific skipped in the Child case, consider reworking your design to better represent what you need (e.g. maybe you need to override something else in the Child class, too). Or, you could provide another Foo() in the Parent class that doesn't do anything except call its base.Foo().
If you have control of the code, the simplest way is to create a protected method in Parent class that only call base.Foo() and your child class Foo implementation call that method explicitly
We had exactly this scenario on a large project where the derived methods were called from various locations. Due to change management and QA scripts not to be broken, among other constraints, "drastic" refactoring and class re-structuring are not always possible on a large mature project. Also we did not want to override the method and exclude all base functionality. Most solutions seen elsewhere, looked a bit clumsy, but the solution from Josh Jordan on How to call base.base was quite useful.
However we followed the approach below (which I see now is very similar to what Dan Abramov propose).
public class Base
{
public virtual void Foo()
{
Console.WriteLine("Hello from Base");
}
}
public class Derived : Base
{
public override void Foo()
{
base.Foo();
Console.WriteLine("Text 1");
WriteText2Func();
Console.WriteLine("Text 3");
}
protected virtual void WriteText2Func()
{
Console.WriteLine("Text 2");
}
}
public class Special : Derived
{
public override void WriteText2Func()
{
//WriteText2Func will write nothing when method Foo is called from class Special.
//Also it can be modified to do something else.
}
}
All these strong opinions...
Sometimes it just makes sense to use 99% of something...
public class Base
{
public virtual void Foo()
{
// Do something
}
}
public class DerivedLevel1 : Base
{
public override void Foo()
{
DerivedLevel1Foo();
}
protected void DerivedLevel1Foo()
{
// Do something
base.Foo();
}
}
public class DerivedLevel2 : DerivedLevel1
{
public override void Foo()
{
DerivedLevel2Foo();
}
protected void DerviedLevel2Foo()
{
// Do something
base.Foo();
}
}
public class Special : Derived
{
public override void Foo()
{
// Don't do DerivedLevel2Foo()
base.DerivedLevel1Foo();
}
}

Categories