Home > Software design >  Reference inheriting class in base class method?
Reference inheriting class in base class method?

Time:09-25

I'm looking for the best way to provide a method in an (abstract) base class, which all inheriting classes should be able to use.
This method needs to reference fields and properties of the inheriting types.
Is there a way to provide such a prototype method which doesn't require me to either:

  • Pass a reference to each inheriting instance in question
  • Implement a method on each inheriting class which passes a reference to itself to the base class's method
  • Write an extension method for implementing classes

All of the above work, but seem somewhat inconvenient and unelegant in their own way.

Here is an example where I implemented the three above methods of referencing the inheriting class:

using System;

namespace Test
{
    public abstract class BaseClass
    {
        public void ReferenceInheriting(object InheritingInstance)
        {
            Console.WriteLine("Do things specific to the inheriting class or instance thereof: "   InheritingInstance.GetType().Name);
        }
    }
    public class Inheriting : BaseClass
    {
        public void MakeUseOfBaseClassImplementation()
        {
            base.ReferenceInheriting(this);
        }
    }
    
    public static class Extensions
    {
        public static void BeAvailableForAllImplementing(this BaseClass Inh)
        {
            Console.WriteLine("Do things specific to the inheriting class or instance thereof: "   Inh.GetType().Name);
        }
    }
    
    class program
    {
        public static void Main(string[] args)
        {
            Inheriting inh = new Inheriting();
            Console.WriteLine("Method 1: Calling the inherited method from an inheriting instance, passing a reference to the instance:");
            inh.ReferenceInheriting(inh);
            Console.WriteLine("Method 2: Implementing call to the base class's method in own class:");
            inh.MakeUseOfBaseClassImplementation();
            Console.WriteLine("Method 3: Extension method for all implementing classes:");
            inh.BeAvailableForAllImplementing();
        }
    }
}

The three approaches all produce the same output, but have drawbacks.
Short of parsing caller information, is there another way to do this?
It's not a big deal of course, but I'm interested in making this method as user friendly as possible, both for implementing inheritance and for calling.

Thank you!

CodePudding user response:

You don't need any of that.

This:

    public void reflectInheriting(object inheritingInstance)
    {
        Console.WriteLine("Do things specific to the inheriting class or instance thereof: "   inheritingInstance.GetType().Name);
        FieldInfo fi = inheritingInstance.GetType().GetField("getMe");
        Console.WriteLine(fi.GetValue(inheritingInstance));
    }

Can be rewritten as simply:

    public void reflectInheriting()
    {
        Console.WriteLine("Do things specific to the inheriting class or instance thereof: "   this.GetType().Name);
        FieldInfo fi = this.GetType().GetField("getMe");
        Console.WriteLine(fi.GetValue(this));
    }

And that's all you need.

C# saves the actual underlying type of an object regardless of how it's cast, so even inside BaseClass, this.GetType() will be Inheriting.


Program output to prove nothing has changed:

Method 1: Calling the inherited method from an inheriting instance, passing a reference to the instance:

Do things specific to the inheriting class or instance thereof: Inheriting

Use me in BaseClass


Method 2: Implementing call to the base class's method in own class:

Do things specific to the inheriting class or instance thereof:
Inheriting

Use me in BaseClass


Method 3: Extension method for all implementing classes:

Do things specific to the inheriting class or instance thereof: Inheriting

Use me in BaseClass

CodePudding user response:

You could use Reflection, but that is kind of a weapon of last resort. The idiomatic way to access a property or method in a descendent class is to make it abstract in the base class.

public abstract class BaseClass
{
    public void GetInheriting()
    {
        Console.WriteLine("GetMe is: {0}", this.GetMe);
    }

    protected abstract string GetMe { get; }
}

public class Inheriting : BaseClass
{
    protected override string GetMe => "Use me in BaseClass"; 
    
    public void MakeUseOfBaseClassImplementation()
    {
        base.GetInheriting();
    }
}

public class Program
{
    static public void Main()
    {
        var o = new Inheriting();
        o.MakeUseOfBaseClassImplementation();
    }
}

Link to Fiddle

Output:

GetMe is: Use me in BaseClass
  • Related