我有几个类实际上不需要任何状态。从组织的角度来看,我想把他们放在层次结构中。
但是我似乎不能为静态类声明继承。
就像这样:
public static class Base
{
}
public static class Inherited : Base
{
}
不会起作用。
为什么语言的设计者们拒绝了这种可能性呢?
我有几个类实际上不需要任何状态。从组织的角度来看,我想把他们放在层次结构中。
但是我似乎不能为静态类声明继承。
就像这样:
public static class Base
{
}
public static class Inherited : Base
{
}
不会起作用。
为什么语言的设计者们拒绝了这种可能性呢?
当前回答
不能继承静态类的主要原因是它们是抽象且密封的(这也阻止了创建它们的任何实例)。
所以这个:
static class Foo { }
编译到这个IL:
.class private abstract auto ansi sealed beforefieldinit Foo
extends [mscorlib]System.Object
{
}
其他回答
嗯…如果你只是用静态方法填充非静态类,情况会有很大不同吗?
当我试图对第三方库编写IComparer<T>实现时,我遇到了这个问题,其中T是嵌入在类中的enum,如下所示:
public class TheClass
{
public enum EnumOfInterest
{
}
}
但是因为枚举是在第三方库类中定义的,所以我不能编写比较器,因为下面给出了“不能扩展列表”错误:
public class MyComparer : IComparer<TheClass.EnumOfInterest>
{
}
我甚至没有扩展静态类——我只是实现类中定义的枚举的比较器。
不能继承静态类的主要原因是它们是抽象且密封的(这也阻止了创建它们的任何实例)。
所以这个:
static class Foo { }
编译到这个IL:
.class private abstract auto ansi sealed beforefieldinit Foo
extends [mscorlib]System.Object
{
}
我的回答是:糟糕的设计选择。: -)
这是一场关于语法影响的有趣辩论。在我看来,争论的核心是一个设计决策导致了密封的静态类。关注静态类的名称出现在顶层的透明度,而不是隐藏在子名称后面(“混乱”)?人们可以想象语言实现可以直接访问基类或子类,这很令人困惑。
这是一个伪示例,假设以某种方式定义了静态继承。
public static class MyStaticBase
{
SomeType AttributeBase;
}
public static class MyStaticChild : MyStaticBase
{
SomeType AttributeChild;
}
会导致:
// ...
DoSomethingTo(MyStaticBase.AttributeBase);
// ...
哪个可能(会?)影响相同的存储
// ...
DoSomethingTo(MyStaticChild.AttributeBase);
// ...
很困惑!
但是等等!编译器如何处理MyStaticBase和MyStaticChild在两者中定义了相同的签名?如果子覆盖比我上面的例子不会改变相同的存储,也许?这导致了更多的困惑。
我相信有限的静态继承有很强的信息空间理由。稍后会详细介绍极限。这个伪代码显示了以下值:
public static class MyStaticBase<T>
{
public static T Payload;
public static void Load(StorageSpecs);
public static void Save(StorageSpecs);
public static SomeType AttributeBase
public static SomeType MethodBase(){/*...*/};
}
然后你会得到:
public static class MyStaticChild : MyStaticBase<MyChildPlayloadType>
{
public static SomeType AttributeChild;
public static SomeType SomeChildMethod(){/*...*/};
// No need to create the PlayLoad, Load(), and Save().
// You, 'should' be prevented from creating them, more on this in a sec...
}
用法如下:
// ...
MyStaticChild.Load(FileNamePath);
MyStaticChild.Save(FileNamePath);
doSomeThing(MyStaticChild.Payload.Attribute);
doSomething(MyStaticChild.AttributeBase);
doSomeThing(MyStaticChild.AttributeChild);
// ...
创建静态子对象的人不需要考虑序列化过程,只要他们了解平台或环境的序列化引擎上可能存在的任何限制。
静态变量(单例和其他形式的“全局变量”)经常出现在配置存储中。静态继承将允许这种职责分配在语法中清晰地表示,以匹配配置的层次结构。但是,正如我所指出的,如果实现基本的静态继承概念,就有可能产生大量的歧义。
我相信正确的设计选择是允许静态继承,但有特定的限制:
没有重写任何东西。子元素不能替换基底元素 属性、字段或方法…重载应该是可以的 只要有不同的签名允许编译器 整理出child和base。 只允许通用静态基,不能继承 非通用静态基。
您仍然可以通过通用引用MyStaticBase<ChildPayload>. somebasefield来更改相同的存储。但是您可能会感到气馁,因为必须指定泛型类型。而子引用会更干净:MyStaticChild.SomeBaseField。
我不是编译器的作者,所以我不确定我是否忽略了在编译器中实现这些限制的困难。也就是说,我坚信有限的静态继承需要信息空间,基本的答案是你不能因为糟糕的(或过于简单的)设计选择。
当创建只包含静态成员和私有构造函数的静态类时。唯一的原因是静态构造函数阻止类被实例化,因为我们不能继承静态类。访问静态类成员的唯一方法是使用类名本身。试图继承静态类并不是一个好主意。