Smalltalk - 在这种情况下如何避免类型检查?

Smalltalk - How to avoid typechecks in this situation?

这是一个例子。

假设以下约束:

我有以下 类:

功能:

    AbstractShop>>addProduct: aProduct
    (products size < 5)
    ifTrue:[^ products add:aProduct]
    ifFalse:[ self error: 'A shop can only have five products' ]

    FoodShop>>addProduct: aProduct
    (aProduct isMemberOf: Food)
    ifTrue:[^ super addProduct: aProduct]
    ifFalse:[ self error: 'You can only add food products to a foodshop' ]

    ClothesShop>>addProduct: aProduct
    (aProduct isMemberOf: Clothing)
    ifTrue:[^ super addProduct: aProduct]
    ifFalse:[ self error: 'You can only add clothing products to a clothes shop' ]

"ClothesShop doesn't override the addProduct, because it can add them both."

如何避免检查产品类型以查看是否可以添加到商店?我想避免这种情况,因为它很难闻。我尝试用 Double Dispatch 解决这个问题,但它似乎使代码更难维护。

这是我们多次使用的模式。 class 声明哪些事物(或 classes 的实例)可以处理。

AbstractShop class >> allowedProducts
   self subclassResponsibility

FoodShop class >> allowedProducts
   ^#(Food)

ClothesShop class >> allowedProducts
   ^#(Clothing)

MixedShop class >> allowedProducts
   ^AbstractProduct subclasses

AbstractShop >> isAllowed: aProduct
   ^self class allowedProducts includes: aProduct class

 AbstractShop>>addProduct: aProduct
    products size < 5
       ifFalse:[ self error: 'A shop can only have five products' ].
    (self isAllowed: aProduct) 
       ifFalse: [self error: 'Product not allowed in this shop' ].
    ^ products add:aProduct

并且您不应该重新定义 addProduct。

但如果闻起来有什么问题,容量检查中的魔法常量 5 也应该被提取出来,并且你应该将产品的验证与添加分开。

我从来不喜欢称呼 class AbstractSomething,那也是一种难闻的气味。在您的情况下,仅使用 Shop 和 Product 就足够抽象了。

你也可以使用双重分派来做到这一点:

AbstractShop>>addProduct: aProduct
  (products size < 5)
    ifTrue:[ ^ aProduct addToShop: self ]
    ifFalse:[ self error: 'A shop can only have five products' ]

AbstractShop>>addFoodProduct: aProduct
  ^ self subclassResponsibility

AbstractShop>>addClothingProduct: aProduct
  ^ self subclassResponsibility

FoodShop>>addFoodProduct: aProduct
  ^ products add: aProduct

FoodShop>>addClothingProduct: aProduct
  self error: 'You can only add clothing products to a clothes shop'

AbstractProduct>>addToShop: aShop
  ^ self subclassResponsibility

Food>>addToShop: aShop
  ^ aShop addFoodProduct: self

Clothing>>addToShop: aShop
  ^ aShop addClothingProduct: self

关于您的用例,我认为最好有一组受支持的商品,因为您可能有许多商店具有不同的商品组合。但是使用双重分派你永远不会检查类型。