我最近一直与提供商合作,我遇到了一个有趣的情况,我希望有一个抽象的静态方法。 我读了一些关于这个主题的帖子,这有点意义,但有一个很清楚的解释吗?
为什么我不能在C#中使用抽象静态方法?
Why can't I have abstract static methods in C#?
===============>>#1 票数:152 已采纳
静态方法不是这样实例化的 ,它们只是在没有对象引用的情况下可用。
对静态方法的调用是通过类名完成的,而不是通过对象引用,调用它的中间语言(IL)代码将通过定义它的类的名称调用抽象方法,不一定是你使用的课程。
让我举个例子。
使用以下代码:
public class A
{
public static void Test()
{
}
}
public class B : A
{
}
如果你打电话给B.Test,就像这样:
class Program
{
static void Main(string[] args)
{
B.Test();
}
}
那么Main方法中的实际代码如下:
.entrypoint
.maxstack 8
L0000: nop
L0001: call void ConsoleApplication1.A::Test()
L0006: nop
L0007: ret
正如你所看到的那样,调用A.Test,因为它是定义它的A类,而不是B.Test,即使你可以用这种方式编写代码。
如果您有类类型 ,比如在Delphi中,您可以在其中创建一个引用类型而不是对象的变量,那么您将更多地使用虚拟和抽象静态方法(以及构造函数),但它们不可用,因此静态调用在.NET中是非虚拟的。
我意识到IL设计者可以允许编译代码来调用B.Test,并在运行时解析调用,但它仍然不是虚拟的,因为你仍然需要在那里编写某种类名。
虚拟方法以及抽象方法仅在您使用变量时才有用,该变量在运行时可以包含许多不同类型的对象,因此您希望为变量中的当前对象调用正确的方法。 使用静态方法,无论如何都需要通过类名,因此在编译时需要确切的调用方法,因为它不会也不会更改。
因此,.NET中不提供虚拟/抽象静态方法。
===============>>#2 票数:43
静态方法不能被继承或覆盖,这就是为什么它们不能是抽象的。 由于静态方法是在类的类型而不是实例上定义的,因此必须在该类型上显式调用它们。 因此,当您想要在子类上调用方法时,您需要使用其名称来调用它。 这使得继承无关紧要。
假设您可以暂时继承静态方法。 想象一下这种情况:
public static class Base
{
public static virtual int GetNumber() { return 5; }
}
public static class Child1 : Base
{
public static override int GetNumber() { return 1; }
}
public static class Child2 : Base
{
public static override int GetNumber() { return 2; }
}
如果你调用Base.GetNumber(),将调用哪个方法? 返回哪个值? 很容易看出,如果不创建对象实例,继承就相当困难。 没有继承的抽象方法只是没有主体的方法,因此无法调用。
===============>>#3 票数:17
另一位受访者(McDowell)表示,多态只适用于对象实例。 那应该是合格的; 有些语言将类视为“类”或“元类”类型的实例。 这些语言确实支持实例和类(静态)方法的多态性。
C#,就像之前的Java和C ++一样,不是这样的语言; static
关键字明确用于表示该方法是静态绑定的而不是动态/虚拟的。
===============>>#4 票数:8
在这种情况下,静态字段和方法肯定需要继承:
abstract class Animal
{
protected static string[] legs;
static Animal() {
legs=new string[0];
}
public static void printLegs()
{
foreach (string leg in legs) {
print(leg);
}
}
}
class Human: Animal
{
static Human() {
legs=new string[] {"left leg", "right leg"};
}
}
class Dog: Animal
{
static Dog() {
legs=new string[] {"left foreleg", "right foreleg", "left hindleg", "right hindleg"};
}
}
public static void main() {
Dog.printLegs();
Human.printLegs();
}
//what is the output?
//does each subclass get its own copy of the array "legs"?
===============>>#5 票数:8
为了添加到前面的解释,静态方法调用在编译时绑定到特定方法,而不是排除多态行为。
===============>>#6 票数:5
我们实际上覆盖了静态方法(在delphi中),它有点难看,但它可以很好地满足我们的需求。
我们使用它,所以类可以有一个没有类实例的可用对象列表,例如,我们有一个如下所示的方法:
class function AvailableObjects: string; override;
begin
Result := 'Object1, Object2';
end;
它很丑陋但很必要,这样我们可以实例化所需的内容,而不是只是为了搜索可用的对象而实例化所有类。
这是一个简单的示例,但应用程序本身是一个客户端 - 服务器应用程序,它只有一个服务器中的所有类,以及多个不同的客户端,这些客户端可能不需要服务器拥有的所有内容,也永远不需要对象实例。
因此,与为每个客户端安装一个不同的服务器应用程序相比,这更容易维护。
希望这个例子很清楚。
===============>>#7 票数:0
抽象方法是隐式虚拟的。 抽象方法需要实例,但静态方法没有实例。 因此,您可以在抽象类中使用静态方法,它不能是静态抽象(或抽象静态)。