【问题标题】:Enforcing and contract methods in SqueakSqueak 中的执行和合同方法
【发布时间】:2014-12-12 08:36:44
【问题描述】:

所以我创建了一个类来强制发送到它的类实例的每个方法(消息)。

即代码:

|a|
a := Animal new.
a makeSound: 'bark'

应该导致对“doesNotUnderstand”的调用(即使它存在于类中)并且它应该检查 post 和 pre 条件是否存在,我将解释: 如果一个方法看起来像这样:

    makeSound: aNoise
 "%self assert: [canMakeNoise = true]%"
 "@self assert: [numOfLegs >= 0]@"
 numOfLegs := -1

这意味着除了那个main方法之外,还有一个方法叫做:PREmakeSound,它的实现是:

self assert: [canMakeNoise = true]

还有一个名为 POSTmakeSiund 的方法,其实现如下:

self assert: [numOfLegs >= 0]

---我的问题是 - 因为每个方法调用都在调用 dosNotUnderstand,所以每当我想实际激活该方法时(在我检查了我需要的任何内容之后)我如何才能按原样激活它? 希望我的问题很清楚...

【问题讨论】:

    标签: oop smalltalk squeak design-by-contract


    【解决方案1】:

    也许使用方法包装器比使用#doesNotUnderstand: 效果更好?

    使用compiledMethod 实例变量创建一个类PrePostMethod。然后,您可以在类的方法字典中安装 PrePostMethod 的实例,而不是 CompiledMethod 的实例。

    当 VM 查找消息并获取此 PrePostMethod 实例而不是 CompiledMethod 时,它不知道如何处理它。因此,它将向该 PrePostMethod 对象发送“run: aSelector with: arguments in: receiver”。您可以在此处执行自定义操作,例如检查前置条件。

    例如:

    PrePostMethod>>run: aSelector with: arguments in: receiver
        | result |
        self checkPrecondition: receiver
        result := compiledMethod run: aSelector with: arguments in: receiver
        self checkPostCondition: receiver.
        ^ result
    

    正如 Sean 所建议的,另一种解决方案是更改这些方法的编译方式。 您可以在编译之前转换方法的 AST,或者更改编译过程本身。例如,使用 AST 转换方法,您可以转换:

    makeSound: aNoise
        "%self assert: [ self canMakeNoise]%"
        "@self assert: [ self numOfLegs >= 0]@"
        numOfLegs := -1
    

    进入:

    makeSound: aNoise
        self assert: [ 
            "The preconditions goes here" 
            self canMakeNoise ]
        ^ [ "Original method body + self at the end if there is no return"
            numOfLegs := -1.
            self ] ensure: [ 
                "The postcondition goes here" 
                self assert: [ self numOfLegs >= 0 ] ]
    

    一方面,这些解决方案实施起来会更加繁琐,但另一方面,它们的性能更高。

    HTH

    【讨论】:

      【解决方案2】:

      您能否详细解释一下您为什么使用doesNotUnderstand?我的第一个想法是在编译期间注入额外的字节码......

      虽然,从doesNotUnderstand 发送消息的方式类似于: self perform: newSelector withArguments: aMessage arguments.

      问题是,如果这个消息是这样很容易陷入无限循环。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-12
        • 2016-02-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多