C# 从基类获取方法?

C# 从基类获取方法?,c#,.net,base,C#,.net,Base,我是全新的基类,所以如果我错了,请纠正我,或者我应该用另一种方式来做,但我在下面编写了一个简单的代码片段,解释了我想要做什么 class A : B { private int _classId; public A (int id) : base(id) { _classId = id; } public string GetString() { return "This will eventually be a

我是全新的基类,所以如果我错了,请纠正我,或者我应该用另一种方式来做,但我在下面编写了一个简单的代码片段,解释了我想要做什么

class A : B
{
    private int _classId;

    public A (int id) : base(id)
    {
        _classId = id;
    }

    public string GetString()
    {
        return "This will eventually be an important string.";
    }
}

class B
{
    private int _classId;

    public B (int id)
    {
        // here I want to be able to get access to class A's methods
        // such as GetString() ...
    }

    public void SomeMethod()
    {

    }
}
所以我想做的是允许B得到A的方法

为什么要这样做? 我不想填充类A,因为B将有很多方法,所以将它们保留在B中,然后在其他代码中从A中获取它们会更干净。我做错了吗?这不是基类所做的吗?我只是想继续这样做:

A.SomeMethodInB();

如果该方法仅在
类A
中定义,则无法通过
类B
访问该方法,而不使用垃圾填充类A并通过将其存储在类B中使其更干净


如果该方法同时存在于
A类
B类
中,则可以使用
虚拟
方法和
覆盖

我认为最好在示例中使用名称BaseClass和DerivedClass。A和B的名字有点随意。虽然A排在B之前,但名称并不意味着继承的方向

class Program
    {
        static void Main(string[] args)
        {
            var bc = new BaseClass(3);
            var dc = new DerivedClass(5);

            Console.WriteLine("Base Class Method A: " + bc.MethodA());
            Console.WriteLine("Derived Class Method A: " + dc.MethodA());
            Console.WriteLine("Base Class Method B: " + bc.MethodB());
            Console.WriteLine("Derived Class Method B: " + dc.MethodB());
            Console.ReadLine();
        }
    }

    public class BaseClass {
        protected int _classId;

        public BaseClass(int classId) {
            _classId = classId;
        }

        public virtual string MethodA() {
            return "Method A in base class: " + _classId.ToString();
        }

        public string MethodB()
        {
            return "I am a method B in the base class: " + _classId.ToString();
        }
    }

    public class DerivedClass : BaseClass {
        public DerivedClass(int classId)
            : base(classId)
        {

        }

        public override string MethodA() {
            return "Method A in derived class: " + _classId.ToString();
        }
    }

有两种方法可以做到这一点。让我先举个例子

这里我们有一个基类,它包含一个方法:

public class Base
{
    public void BaseMethod()
    {
        // Some method.
    }
}
这是派生类,我们要在其中调用该方法:

public class DerivedClass : BaseClass
{
    // We want to use BaseMethod() here.
}
为了从基类调用方法,我们使用
base
关键字

public class DerivedClass : BaseClass
{
    base.BaseMethod();
}
如果您只想调用基本方法,这是很好的。但是,如果我们想更改方法并用不同的函数定义它,我们必须在基类中将其声明为
virtual
,如下所示:

public class Base
{
    public virtual void BaseMethod()
    {
        // Some method.
    }
}
在派生类中,我们现在可以使用关键字
override
来重写基类的虚方法,它重新定义基类以执行其他操作:

public class DerivedClass : BaseClass
{
    public override void BaseMethod()
    {
        // Some new function.
    }
}

让我总结一下你的问题:

  • 您需要一个只在子类(a)中实现的方法
  • 您希望基类(B)和子类(A)都可以使用此方法
  • 您希望基类能够调用该方法的子类实现
这是多态性的原始定义(最近人们更普遍地使用这个术语),对于OOP来说,这是一个基本概念。对于新手来说,这也是OOP中最难掌握的领域

使用虚方法编写基类 让我们从基类开始。请注意,我稍微更改了您的示例,稍后我将解释其中的原因

class B
{
    virtual protected string GetString()
    {
        return "I am a B";
    }

    public void DoSomethingWithGetString()
    {
        Console.WriteLine(GetString());
    }
}
在本例中,
DoSomethingWithGetString
调用
GetString
。请注意,
GetString
是虚拟的。这告诉编译器,在运行时之前,我们不想决定
GetString
的实现在哪里。这意味着它不能在编译时绑定:相反,它的位置由创建对象时设置的运行时标识。如果此代码作为类B实例的一部分运行,那么它将调用类B的
GetString
实现。但是,如果此代码是继承的,并且实际上正被从类B派生的其他对象调用,则它将调用该类的版本
GetString
。这就是所谓的

编写后代类 现在让我们来写一个类:

class A : B
{
    protected override GetString()
    {
        return "I am an A.";
    }
}
因为A是B的后代,所以我们不需要实现其他任何东西。如果我们调用
A.DoSomethingWithGetString
,它实际上会调用B的实现,因为它是继承的

执行它 如果您运行此代码

var a = new A();
a.DoSomethingWithGetString();  //Output = "I am an A"
…将发生以下情况:

  • 将创建从B派生的A实例
  • 对的VMT进行了配置,以便将对
    GetString
    的调用发送到.GetString
  • 您可以调用A.DoSomethingWithGetString
  • 这个调用被定向到B的代码库,因为A没有实现它
  • B中的代码库检测到GetString是一个虚拟方法,并使用VMT调用它
  • VMT指向A的GetString实现
  • 执行一个.GetString
  • 因此,您会遇到这样一种情况:类B中的代码正在调用类A中的代码,这就是您所要求的

    您也可以这样运行它:

    B b = new A();
    b.DoSomethingWithGetString(); //Output = "I am an A"
    
    因此,您有一个指向B的指针,表示它是a,因为它使用为类a设置的VMT

    但我不想在B类中实现任何功能 现在,假设您根本不希望类B拥有GetString的任何实现,但是您仍然希望能够在A中调用该实现。只需添加abstract关键字并删除实现:

    abstract class B
    {
        abstract protected string GetString(); //Notice no implementation
    
        public void DoSomethingWithGetString()
        {
            Console.WriteLine(GetString());
        }
    }
    
    当然,现在不能单独使用类B,因为它需要一个GetString的实现,该实现只存在于子类中。因此,您不能再直接创建B的实例;您必须使用子类型,并使用子类型

    不能使用构造函数 现在,您会注意到在我的示例中,我删除了您的构造函数调用。这是有原因的。构造函数不应该调用在子类上定义的方法。原因是:在构造过程中,构造函数在继承层次结构中上下调用,从基类开始,向下移动到后代链。这意味着,当你调用B的构造函数时,A的构造函数还没有被调用。如果A的构造函数还没有运行,我们无法确定A是否已经正确设置,因此调用它的任何方法都是一个非常糟糕的主意


    对此有一些解决方法,但这是a的主题。

    您应该查看受保护关键字的此引用:我认为,您错误地放置了基类和派生类,根据您的解释,我理解,您应该使一个类具有许多受保护的基类方法,让b类从itSo派生,我想做的是允许b得到A的方法。不,正好相反
    A
    B
    获取方法。如果你