如何将契约绑定到匿名类定义

时间:2014-08-14 16:19:58

标签: racket

我有一个返回类定义的方法:

(define (max-tracker%)
  (let ([current-maximum 0])
    (class object%
      (init val) ; <--
      ...
      (define held-value 0)
      (set-val val)
      (define/public (set-val newval) ; <--
        (when (newval . >= . current-maximum)
          (set! current-maximum newval))
        (set! held-value newval))
      ...
      )))

如何将合约绑定到set-val方法?

1 个答案:

答案 0 :(得分:4)

您可以使用with-contract表单,该表单允许您在表达式中创建任意合约区域:

(define (max-tracker%)
  (with-contract
    max-tracker-procedure
    #:result contract-expr
    (class object% (init val) ...)))

这将创建一个名为max-tracker-procedure的合同区域,该区域只导出一个必须符合contract-expr中指定的合同的匿名值。在这种情况下,您可以指定class/c合同。通过使用Racket返回多个值并使用#:results (contract-expr ...)的能力,也可以指定多个值和导出。这是一个更简单的例子来证明这一点:

(define test-value
  (with-contract test
    #:result (or/c integer? symbol?)
    "neither int nor symbol - should break contract"))

运行它应该会给你:

broke its contract:
promised: (or/c integer? symbol?)
produced: "neither int nor symbol - should break contract"
in: (or/c integer? symbol?)
contract from: (region test)
blaming: (region test)

将此与class/c相结合可以为您提供所需的信息。

修改

这是一个更接近你想要的例子:

(define (with-greeting class%)
  (with-contract with-greeting
    #:result (class/c [greet (->m string? string?)])
    (class class%
      (super-new)
      (define/public (greet person)
        (string-append "Hello, " person "!")))))

(define simple-greeter% (with-greeting object%))
(define simple-greeter (new simple-greeter%))
(send simple-greeter greet "Jack")
(send simple-greeter greet 'Jack)