【问题标题】:Reference inheriting class in base class method?在基类方法中引用继承类?
【发布时间】:2021-11-17 22:20:31
【问题描述】:

我正在寻找在(抽象)基类中提供方法的最佳方式,所有继承类都应该能够使用该方法。
此方法需要引用继承类型的字段和属性。
有没有办法提供这样一个不需要我的原型方法:

  • 传递对每个有问题的继承实例的引用
  • 在每个继承类上实现一个方法,它将对自身的引用传递给基类的方法
  • 为实现类编写扩展方法

上述所有工作,但在他们自己的方式似乎有些不方便和不优雅。

下面是一个例子,我实现了上面三个引用继承类的方法:

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();
        }
    }
}

这三种方法都产生相同的输出,但都有缺点。
缺少解析来电者信息,有没有其他方法可以做到这一点?
当然这没什么大不了的,但我有兴趣让这个方法尽可能地对用户友好,无论是实现继承还是调用。

谢谢!

【问题讨论】:

  • 为什么要在这里使用反射?如果 BaseClass 有合法用途,为什么不声明 getMe
  • 附带说明:如果您遵循正常的命名约定,即使对于示例代码,它也会很有帮助。对于阅读问题或试图回答您的人来说,任何非常规的内容都会分散您的注意力。
  • @JonSkeet 您具体指的是命名约定的哪些方面?当然,名字可能有点长,但我认为他们描述了我对他们的期望,好吧
  • @BenPhilipp:reflectInheriting 应该是 ReflectInheritinggetMe 应该是 GetMe,等等。我认为问题不在于长度,而在于大小写。它也让我有点失望。
  • @ThomasBonini 哦!我看到了

标签: c# .net inheritance


【解决方案1】:

你不需要这些。

这个:

    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));
    }

可以简单地改写为:

    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));
    }

这就是你所需要的。

C# 保存对象的实际底层类型,不管它是如何转换的,所以即使在 BaseClass 内部,this.GetType() 也将是 Inheriting


证明没有任何变化的程序输出:

方法一:从继承的实例调用继承的方法,传递对实例的引用:

做特定于继承类或其实例的事情:继承

在 BaseClass 中使用我


方法二:在自己的类中实现对基类方法的调用:

做特定于继承类或其实例的事情:
继承

在 BaseClass 中使用我


方法3:所有实现类的扩展方法:

做特定于继承类或其实例的事情:继承

在 BaseClass 中使用我

【讨论】:

  • 什么...这是如此基本的行为,我不敢相信我不知道它是如何工作的! ?‍♂️谢谢!
【解决方案2】:

您可以使用反射,但这是一种最后的武器。在派生类中访问属性或方法的惯用方式是在基类中将其抽象化。

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

输出:

GetMe is: Use me in BaseClass

【讨论】:

  • 反射是我首先想要实现的一部分。请注意,我并没有尝试使用反射来获取对该类的引用,并且它不用于尝试回答问题。实际实现为所有继承类提供自定义功能,需要从中获取属性和字段
  • 很公平......当有人提出问题时,很难说他们知道多少,不知道多少,我不想错过“正常”的方法。我相信您有充分的理由使用反射。
  • 很抱歉造成了一些混乱,我想我会让我的部分代码作为使用继承类的示例,但似乎这是一个坏主意?反射现在从我的问题中删除。感谢您的时间和投入,对不起,我在试图说明我的问题时不太清楚^^
猜你喜欢
  • 1970-01-01
  • 2012-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多