我有几个类实际上不需要任何状态。从组织的角度来看,我想把他们放在层次结构中。
但是我似乎不能为静态类声明继承。
就像这样:
public static class Base
{
}
public static class Inherited : Base
{
}
不会起作用。
为什么语言的设计者们拒绝了这种可能性呢?
我有几个类实际上不需要任何状态。从组织的角度来看,我想把他们放在层次结构中。
但是我似乎不能为静态类声明继承。
就像这样:
public static class Base
{
}
public static class Inherited : Base
{
}
不会起作用。
为什么语言的设计者们拒绝了这种可能性呢?
当前回答
我的回答是:糟糕的设计选择。: -)
这是一场关于语法影响的有趣辩论。在我看来,争论的核心是一个设计决策导致了密封的静态类。关注静态类的名称出现在顶层的透明度,而不是隐藏在子名称后面(“混乱”)?人们可以想象语言实现可以直接访问基类或子类,这很令人困惑。
这是一个伪示例,假设以某种方式定义了静态继承。
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。
我不是编译器的作者,所以我不确定我是否忽略了在编译器中实现这些限制的困难。也就是说,我坚信有限的静态继承需要信息空间,基本的答案是你不能因为糟糕的(或过于简单的)设计选择。
其他回答
您希望通过使用类层次结构实现的目标可以通过命名空间实现。因此,支持名称空间的语言(如c#)将无法实现静态类的类层次结构。因为您不能实例化任何类,所以您所需要的只是通过使用名称空间获得的类定义的分层组织
嗯…如果你只是用静态方法填充非静态类,情况会有很大不同吗?
我的回答是:糟糕的设计选择。: -)
这是一场关于语法影响的有趣辩论。在我看来,争论的核心是一个设计决策导致了密封的静态类。关注静态类的名称出现在顶层的透明度,而不是隐藏在子名称后面(“混乱”)?人们可以想象语言实现可以直接访问基类或子类,这很令人困惑。
这是一个伪示例,假设以某种方式定义了静态继承。
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。
我不是编译器的作者,所以我不确定我是否忽略了在编译器中实现这些限制的困难。也就是说,我坚信有限的静态继承需要信息空间,基本的答案是你不能因为糟糕的(或过于简单的)设计选择。
当创建只包含静态成员和私有构造函数的静态类时。唯一的原因是静态构造函数阻止类被实例化,因为我们不能继承静态类。访问静态类成员的唯一方法是使用类名本身。试图继承静态类并不是一个好主意。
你可以做的一个解决方法是不使用静态类,而是隐藏构造函数,这样类的静态成员是类外部唯一可访问的东西。结果是一个可继承的“静态”类:
public class TestClass<T>
{
protected TestClass()
{ }
public static T Add(T x, T y)
{
return (dynamic)x + (dynamic)y;
}
}
public class TestClass : TestClass<double>
{
// Inherited classes will also need to have protected constructors to prevent people from creating instances of them.
protected TestClass()
{ }
}
TestClass.Add(3.0, 4.0)
TestClass<int>.Add(3, 4)
// Creating a class instance is not allowed because the constructors are inaccessible.
// new TestClass();
// new TestClass<int>();
不幸的是,由于“by-design”语言限制,我们无法做到:
public static class TestClass<T>
{
public static T Add(T x, T y)
{
return (dynamic)x + (dynamic)y;
}
}
public static class TestClass : TestClass<double>
{
}