Tcl中的面向对象

@ 2011-07-27 18:39:25
标签:

    这里所谓的面向对象主要是指创建一个类(class),并创建这个类的实例这样一种操作。

    Tcl中没有直接的用于面向对象的命令。Tcl的内置命令中最接近面向对象概念的应该是namespace(命名空间)。

    借助namespace的帮助,可以实现对数据的封装。如果这个类只能有一个实例(instance)的话,我们直接用namespace来模拟就可以了。问题的关键就是如何处理多个实例(instance)的问题。

    实现方案:stooop

    stooopTcllib中一个面向对象编程解决方案。一个简单的例子如下:

    ::stooop::class circle {
      proc circle {this r} { set ($this,r) $r }  ; # 构造函数
      proc ~circle {this} {}                     ; # 析构函数
      proc circle {this copy} {}                 ; # 拷贝构造函数
    
      # 对象方法
      proc area {this args} {
        set area [expr {$this,r)*($this,r)*3.14]
        set ($this,area) $area
      }
    
      # 静态函数
      proc name {args} {
         set (data) 0
         return "circle"
      }
    }
    
    set c [::stooop::new circle 20] ; 创建对象实例
    puts [circle::area $c]          ; 调用对象方法
    ::stooop::delete $c             ; 删除对象实例
    

    可以看出,stooop的使用很像是一个约定了命名规则的namespace(命名空间)。

    实际上stooop的内部实现也确实就是一个namespace。各个实例的数据存储通过this指针进行区分,存储在一个empty array里面。

    在进行方法调用时,我们传递了对象实例的标识作为方法的第一个参数。这也是stooop提供的实现与面向对象的习惯用法不一样的地方。比起circle::area $c这样的用法,大家可能更希望看到$c area这样的习惯用法。

    虽然如此,stooop毕竟是简单的,它对namespace所做的hack较少。

    实现方案:snit

    snit是Tcllib中另一个面向对象的实现。它的用法可以实例如下:

    snit::type circle {
      constructor {_r} { set r $_r }    ; # 构造函数
      destructor {}                     ; # 析构函数
    
      # 成员变量
      variable r
    
      # 对象方法
      method print {args} { puts $args }
    
      method area {args} {
        set area [expr $r*$r*3.14]      ; # 直接使用成员变量
        $self print                     ; # 通过 $self 调用其他方法
      }
    
      # 静态函数
      typemethod name {args} {
         return "circle"
      }
    }
    
    set c [circle create %AUTO% 13]   ; 创建对象实例
    puts [$c area]                    ; 调用对象方法
    $c destroy                        ; 删除对象实例
    circle destroy                    ; 删除对象定义
    

    snit也是基于namespace的实现,但要比stooop复杂的多,当然功能也要强一些。

    实现方案:incr Tcl

    incr Tcl 也提供了面向对象的实现方法 class。它的语法和snit有点相像。

    class circle {
      constructor {_r} { set r $_r }    ; # 构造函数
      destructor {}                     ; # 析构函数
    
      variable r 10                     ; # 成员变量,同时设置默认值
    
      # 对象方法
      method print {args} { puts $args }
    
      method area {args} {
        set area [expr $r*$r*3.14]      ; # 直接使用成员变量
      }
    
      # 静态函数
      proc name {args} { return "circle" }
    }
    
    circle c 13                       ; 创建对象实例
    puts [$c area]                    ; 调用对象方法
    $c destroy                        ; 删除对象实例
    

    其他实现方案

    TODO

    标签:

      分享到:
      comments powered by Disqus

      25/27ms