【问题标题】:Abstract Class in Smalltalk-Squeak. What is it?Smalltalk-Squeak 中的抽象类。它是什么?
【发布时间】:2011-05-02 10:12:06
【问题描述】:

如果我说得对,那么抽象类就是一个至少有一个抽象方法的类?

现在,如果它是抽象的,那么我应该无法创建该类的实例?

就像说Abst是一个抽象类的名字(因为它包含一个抽象方法)这样做:

a := Abst new.

是非法的,应该弹出错误/异常吗? 或者问题应该出现在这里:

a := Abst class new.

?

更新: 正如建议的那样,我制作了下一个方法,它不会让用户创建 Class 的实例,但它不起作用:

makeAbstract: aClass    
    aClass compile: 'new
                ^ self subclassResponsibility'.

【问题讨论】:

    标签: smalltalk squeak


    【解决方案1】:

    欢迎来到 Smalltalk! Smalltalk 的一大优点是它信任开发人员,他们从这种信任带来的力量中受益。所以像“无法”和“非法”这样的词很少适用。

    与大多数其他事物一样,Smalltalk 中的抽象类更像是一个建议/指针,而不是严格的法律。您寻找的两条线索是#subclassResponsibility 和#shouldNotImplement。这两种方法是子类是否包含特定方法的线索。检查发件人在图片中的示例(始终是问题的一个很好的起点)。

    如上所述,由于“抽象”实际上是基于每个方法的,因此您的示例不会产生错误(除非从初始化中调用 #subclassResponsibility 或 #shouldNotImplement。

    两件小事:

    • 类名大写 Smalltalk,如此抽象,而不是抽象。
    • 谷歌搜索有很长的路要走。三 在四个顶级链接中 “smalltalk抽象类”都是 你需要(this one 特别好看)。

    更新:如果您想向您班级的用户发出信号,他们不应该创建实例(如下面的评论中所示),您可以这样写:

    Abstract>>new
        ^ self subclassResponsibility.
    

    然后“Abstract new” -> 报错,但是“AbstractSubclass new”没问题。

    虽然仍然不能保证 AbstractSubclass 已经覆盖了抽象方法(不是#new,而是导致您一开始就想要阻止实例化的方法),但实际上这不会成为问题。如果您真的想这样做,您可以检查一下,也许在#initialize 中,以确保没有实例的方法调用#subclassResponsibility,但除非您有充分的理由,否则不要打扰。

    更新 2:使类抽象的实用方法是:

    Class>>makeAbstract
    
        self class compile: 'new
                    ^ self subclassResponsibility'.
    

    【讨论】:

    • 谢谢,所以如果没有“非法”或“无法”之类的东西,抽象类与不创建此类实例之间的实际联系是什么?例如,如果我有一个类,我在运行时添加了一个抽象方法,然后(仍然在运行时)当我尝试创建该类的实例时,我希望它生成一个错误,所以它不会让我那个例子。应该在哪里处理?
    • @Sean DeNigris,我试过这样做,但调用 new 时没有错误。请参阅上面的更新。
    • 你很亲密。请参阅我对上面方法主体的编辑(添加了“类”)。您的代码将 #new 放在实例端。另外,如果你把它放在 Class 中,你不必传递类名。
    • @Sean DeNigris,谢谢,现在它可以工作了。那么我所做的是添加到实例中吗?当我刚刚为其他方法执行 aClass compile: 'somecode' 时,我可以在浏览器中看到该方法已添加,因此它确实添加了没有添加“类”的方法,如您所写。有什么不同?是的,我知道不需要类名,但 makeAbstract 是我在自己的类中而不是在类本身中添加的方法。
    • @Sean DeNigris,这与元类有什么关系吗?
    【解决方案2】:

    在 Smalltalk 中,您可以只实例化抽象类。只要您不调用抽象方法,它就可以工作。您可能希望在运行时实现缺失的方法。

    【讨论】:

      【解决方案3】:

      是的,一个抽象类应该至少有一个抽象方法,但是不,您仍然可以创建该类的实例。

      你应该做的是创建从抽象类继承的具体类,你可以创建实例并调用方法。

      Smalltalk 中的抽象方法有一个特定的实现,使它们和类抽象:

      method
          self subclassResponsibility
      

      这也意味着子类应该重写这个方法并提供一个具体的实现。

      如果您看到有关 subclassResponsibility 的错误,您的代码要么调用了抽象类的方法,要么您的子类没有提供该方法的实现。

      【讨论】:

      • 我添加了一个使用 ^ self subclassResponsibility 覆盖某个类的新方法,但在尝试创建该类的实例时仍然没有错误(请参阅上面更新中的代码)。
      【解决方案4】:

      我建议您阅读 Pharo By Example 一书。你可以在这里找到它:http://pharobyexample.org/ 你会发现很多有趣的东西。这是一本免费的开放书,您可以下载pdf。 事实上,你的问题在第 5 章第 88 页中有解释。

      【讨论】:

        【解决方案5】:

        (固定的)“new-blocker”为其具体子类带来了一些不便:它们必须重新定义 new,并且不能使用任何继承的超类的 new em> 功能。 你可以通过一个小守卫来解决这个问题,它会检查它是否真的是试图实例化的抽象类:

        AbstractClass class >> new
            self == AbstractClass ifTrue:[
                ^ self abstractClassInstantiationError
            ].
            ^ super new
        

        (请注意此处的身份比较,即使您将多个抽象类堆叠在一起也有效)

        【讨论】:

        • 您可以在 SUnit 中使用抽象 TestCases 看到类似的问题(和解决方案):寻找 #isAbstract 的实现者。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-03
        • 2022-01-09
        • 1970-01-01
        相关资源
        最近更新 更多