我目前正在尝试深入了解.NET框架。当我想知道是否可以创建两个CommandManagers时,我遇到了一个错误:
Cannot create an instance of CommandManager because it has no public constructors.
显然这意味着:不要这样做,而且有两个人甚至没有意义。 现在我在收到消息之前遇到了另一个错误:
Cannot create an instance of ... because it is sealed
禁止效果相同,但有什么不同。为什么选择一个类没有公共构造函数而不是密封呢?
编辑:
抱歉,我生病了好几天。我进一步混合了两种语言:VB和C#。我打开了两个标签,忽略了一个站在C#上,一个站在VB Code上。一个班级被密封,另一个班级似乎是NonInheritable。我没有意识到这实际上是一样的。现在错误消息变得敏感。
IronPython代码段:
commandManager = CommandManager()
失败
Cannot create instances of CommandManager because it has no public constructors
,而
class MyCommandManager(CommandManager):
return super(MyCommandManager, self).__init__(*args, **kwargs)()
失败了:
cannot derive from System.Windows.Input.CommandManager because it is sealed
我误导了这些错误消息,因为我的google和stackoverflow搜索没有回答(当然因为CommandManager总是密封在C#中,而在VB中始终是NonInheritable) 进一步的CommandManager似乎都是密封的,没有公共构造函数。
答案 0 :(得分:11)
您密封了一个类以防止它被子类化。您删除公共构造函数以防止直接实例化类,通常作为单例模式的一部分。
当然,你可以将两者结合起来。
答案 1 :(得分:2)
Sealed
表示您无法继承它。这就是差异。您仍然可以创建实例,但不能继承。
答案 2 :(得分:1)
sealed
关键字与该类是否可用作基类有关。你绝对可以实例化一个密封的类。
答案 3 :(得分:0)
密封表示无法从中派生子类的类;您的第二个错误必须是指无法创建特定的子类化尝试,而不是尝试创建密封类本身的实例。
不为类声明任何公共构造函数的主要原因是控制其实例的创建。如上所述,这是在 singleton 模式中完成的。这也可以用于 factory 模式实现。在我的游戏引擎中,我为具有多个版本的定义文件的共享部分的各种解析器执行此操作。有时我会把所有建造者都私有化;有时内部;有时受保护以提供不同的控制机制。在这些情况中,我都没有实际执行单例模式。
以下是此用法的摘录:
internal abstract class AbstractParser {
protected TextReader Reader { get; set; }
// etc.
}
internal abstract class MapParser : AbstractParser, IParser<IMapDefinition> {
public abstract IMapDefinition Parse();
protected internal MapParser(TextReader reader) : this() {
Reader = reader;
}
public IMapDefinition Parse(Func<MapHeader, string[], int[][],
HexsideData[,], List<IHpsPlaceName>, int, IMapDefinition> factory
) {
var header = ParseMapHeader(1);
var terrain = ParseTerrain(header.Size);
var elevations = ParseElevation(header.Size);
var feature = ParseFeatures( header.Size);
var placeNames = ParsePlaceNames();
return factory(header, terrain, elevations, feature, placeNames, MaxElevationLevel);
}
// etc.
}
internal class MapV1Parser : MapParser {
internal MapV1Parser(TextReader reader) : base(reader) {}
public override IMapDefinition Parse() {
return base.Parse((h,t,e,f,p,xe) => (new MapDefinitionV1(h,t,e,f,p,xe)));
}
}
internal class MapV2Parser : MapParser {
private readonly Regex regexHeaderLine3;
internal MapV2Parser(TextReader reader) : base(reader) {
regexHeaderLine3 = new Regex(@"^([-]?[0-9]+) ([0-9]+) ([0-9]+) ([0-9]+) ([0-1])$",
RegexOptions.None);
}
public override IMapDefinition Parse() {
return base.Parse((h,t,e,f,p,xe) => (new MapDefinitionV2(h,t,e,f,p,xe)));
}
protected override Line3 ParseHeaderLine3() {
/* Definition override for V3 */
}
}
此基础结构允许在读取第一行后选择适当的MapParser,如下所示:
internal static IParser<IMapDefinition> GetMapParser(TextReader reader) {
string line = reader.ReadLine();
short version;
if (!short.TryParse(line, out version))
Utils.ThrowInvalidDataException("MapParser",1,"Header","Non-integer version number",null,line);
switch(version) {
case 1: return new MapV1Parser(reader);
case 2: return new MapV2Parser(reader);
default: Utils.ThrowInvalidDataException("MapParser",1,"Header","Unknown version number",
null,version);
return null;
}
}
答案 4 :(得分:-1)
一些内部数据
static
实际上是sealed abstract class [ClassName]
abstract
表示必须继承使用它。
sealed
从继承中关闭它,因为我们都知道你无法继承static