如果我说得对,那么抽象类是至少有一个抽象方法的吗?
现在,如果它是抽象的,那么我应该无法创建该类的实例?
就像说Abst
是一个抽象类的名称(因为它包含一个抽象方法)所以这样做:
a := Abst new.
是非法的,应该弹出错误/异常? 或者问题出现在这里:
a := Abst class new.
更新: 正如所建议的那样,我已经制作了下一个方法,它不会让用户创建一个类的实例,但它不起作用:
makeAbstract: aClass
aClass compile: 'new
^ self subclassResponsibility'.
答案 0 :(得分:10)
欢迎来到Smalltalk! Smalltalk的一大优点是它信任开发人员,他们从信任带来的力量中获益。因此,“无法”和“非法”之类的词很少适用。
与大多数其他事物一样,Smalltalk中的抽象类更像是建议/指针而不是严格的法则。您寻找的两条线索是#subclassResponsibility和#shouldNotImplement。无论是否包含特定方法,这两种方法都是子类的线索。检查发件人的图像中的示例(始终是问题的一个很好的起点)。
由于“abstract”,如上所述,实际上是基于每个方法,因此您的示例不会生成错误(除非从初始化调用#subclassResponsibility或#shouldNotImplement。
两件小事:
更新:如果你想向你的班级用户发出他们不应该创建实例的信号(比如下面的评论),你可以写:
Abstract>>new
^ self subclassResponsibility.
然后“抽象新” - >错误,但“AbstractSubclass new”没关系。
虽然仍然无法保证AbstractSubclass覆盖了抽象方法(不是#new,而是导致你想要首先防止实例化的方法),实际上这不会成为问题。如果真的想要,你可以在#initialize中进行检查,确保实例的方法都不会调用#subclassResponsibility,但除非你有充分的理由,否则不要打扰。
更新2:使类抽象的实用方法是:
Class>>makeAbstract
self class compile: 'new
^ self subclassResponsibility'.
答案 1 :(得分:2)
在Smalltalk中,您可以实例化抽象类。只要你不调用抽象方法就可以了。您可能希望在运行时实现缺少的方法。
答案 2 :(得分:2)
是的,抽象类应该至少有一个抽象方法,但不,你仍然可以创建该类的实例。
你应该做的是制作从抽象类继承的具体类,你可以创建实例并调用方法。
Smalltalk中的抽象方法有一个特殊的实现,使它们和类抽象:
method
self subclassResponsibility
这也意味着子类应该重写此方法并提供具体的实现。
如果您看到有关subclassResponsibility的错误,您的代码会在抽象类上调用方法,或者您的子类未提供该方法的实现。
答案 3 :(得分:1)
我建议你阅读Pharo By Example书。你可以在这里找到它:http://pharobyexample.org/ 你会发现很多有趣的东西。这是一本免费的开放式书籍,您可以下载pdf。 事实上,您要问的内容将在第88页的第5章中解释。
答案 4 :(得分:1)
(固定)“new-blocker”为其具体的子类带来了轻微的不便:他们必须重新定义 new ,并且不能使用任何继承的超类' new 功能。 你可以通过一个小小的守卫来解决这个问题,它会检查它是否真的是试图实例化的抽象类:
AbstractClass class >> new
self == AbstractClass ifTrue:[
^ self abstractClassInstantiationError
].
^ super new
(注意这里的身份比较,即使你把多个抽象类叠加在一起,它也能正常工作)