静态方法如何调用虚方法?

时间:2018-03-27 00:58:47

标签: c# .net static override overloading

在为自定义对象编写自己的相等逻辑时,可以做一些事情。其中两种做法包括重载==运算符并覆盖obj.Equals()方法。 下面,我们为父类Animal和子类Hominoidea执行此操作。

public class Animal
{
   public static bool operator ==(Animal x, Animal y)
   {
      return object.Equals(x, y);
   }

   public override bool Equals(object obj)
   { ... }

   ...
}

public class Hominoidea : Animal
{
   public static bool operator ==(Hominoidea x, Hominoidea y)
   {
      return object.Equals(x, y);
   }

   public override bool Equals(object obj)
   { ... }

   ...
}

如果我们能够轻松地比较一种动物的方式而不管它们的派生类(Hominoidea,Felidae等),我们可以利用基类的简单逻辑并且可能会写类似的东西:

static void DisplayWhetherEqual(Animal animal1, Animal animal2)
{
   if (animal1 == animal2)
   {
      Console.WriteLine(string.Format("{0,12} == {1}", animal1, animal2));
   }
   else
      Console.WriteLine(string.Format("{0,12} != {1}", animal1, animal2));
}

如果我们传入Hominoidea个对象,代码将首先执行static类的==重载Animal,然后执行虚拟object.Equals(x, y)子类,Hominoidea类。

将这两个Hominoidea类比较为Animal时,编译器如何在object.Equals()运算符方法中调用正确的虚拟static方法?我认为static方法中的所有内容都必须是static

2 个答案:

答案 0 :(得分:4)

静态方法当然可以访问实例方法;没有它们,你将无法做任何有趣的事情。静态类缺少的是它自己的实例(关键字this在静态方法中是未定义的)。但是,您可以在传递给它的任何对象上调用实例方法,或以其他方式使其可用。

所以虽然你不能这样做

class MyClass
{
    static void Print()
    {
        Console.WriteLine(this.ToString());  //Does not compile
    }
}

你当然可以做到这一点

class MyClass
{
    static void Print(MyClass instance)
    {
        Console.WriteLine(instance.ToString());  //Compiles, because it references an object that was passed in
    }
}

这个

class MyClass
{
    static private MyClass _anInstance = new MyClass();

    static void Print()
    {
        Console.WriteLine(_anInstance.ToString());  //Compiles, because it references an object instance held in a static variable
    }
}

答案 1 :(得分:4)

  

我认为静态方法中的所有内容都必须是静态的

是什么让你这么认为?没有这样的规则。静态方法没有附加到类的特定实例(这就是他们在VB中将它们称为Shared的原因,这意味着它们在所有实例之间共享),但除此之外它们与实例方法没有区别。

考虑一下

public class Person {
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public static string GetInitials(Person person) {
        return person.FirstName[0].ToString() + person.LastName[0].ToString();
    }
}

static方法GetInitials()可以访问传递给它的实例的属性。所以你可以写这段代码:

var p = new Person();
p.FirstName = "Joe";
p.LastName = "Smith";
Console.WriteLine(Person.GetInitials(p));