You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于syntax-rules实现迷你面向对象系统:如何引入this变量?

用syntax-rules实现带this的迷你Scheme面向对象系统

嘿,这个练习超有意思!我之前也折腾过用宏实现迷你OO,核心就是把this绑定到当前实例的消息分发函数上。下面是完全匹配你需求的实现,直接就能用:

(define-syntax oo-class
  (syntax-rules (attr method)
    [(_ ClassName ((attr attr-name attr-default) ...) ((method (method-name param ...) body ...) ...))
     (define (ClassName)
       ;; 每个实例的属性都在闭包里,保证私有性
       (let ([attr-name attr-default] ...)
         ;; 这里的`this`就是实例本身的消息分发器
         (define (this msg)
           (case msg
             ;; 把每个方法映射到对应的lambda
             [(method-name) (lambda (param ...) body ...)] ...
             ;; 可选:支持直接获取属性(如果不需要可以删掉这行)
             [(attr-name) attr-name] ...
             [else (error "Unknown message:" msg)]))
         ;; 返回分发器作为实例对象
         this))]))

核心逻辑说明

  • 当你定义(oo-class Counter ...)时,宏会生成一个构造函数Counter,调用它就会创建一个闭包实例。
  • 属性value和skip被包裹在实例的闭包里,每个实例都有自己的独立副本,完全隔离。
  • this其实就是当前实例的消息分发函数——在方法里写(this 'next),就是拿到当前实例的next方法lambda,接着用((this 'next))执行它。

测试你的示例代码

直接用你给出的代码测试,完全符合预期效果:

(oo-class Counter 
  ((attr value 0) (attr skip 1)) 
  ((method (next) 
     (set! value (+ value skip)) 
     value)
   (method (nextnext) 
     ((this 'next))
     ((this 'next)))
   (method (set-value newval) 
     (set! value newval))
   (method (set-skip newskip) 
     (set! skip newskip))))

(define c (Counter))

((c 'set-value) 23)   ; 设置value为23
((c 'next))            ; 返回24(23+1)
((c 'nextnext))        ; 返回26(24+1+1)
((c 'value))           ; 可选:获取当前value,返回26
((c 'set-skip) 5)      ; 设置步长为5
((c 'next))            ; 返回31(26+5)

小扩展提示

如果不想让外部直接访问属性,把[(attr-name) attr-name] ...删掉就行,这样属性就完全是方法内部的私有变量了。

内容的提问来源于stack exchange,提问作者johnnyb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:06:19