Monday, December 24, 2012

Tcl: Օբյեկտներին կողմնորոշված ծրագրավորման օրինակ

Մի քանի օր առաջ նորությունների կայքում կարդացի Tcl ծրագրավորման լեզվի 8.6 (Tcl 8.6) տարբերակի թողարկման մասին։ Հաղորդագրության մեջ, ի թիվս այլ կետերի, նշվում էր նաև, որ TclOO փաթեթը արդեն հանդիսանում է լեզվի բաղկացուցիչ մաս՝ որպես օբյեկտներին կողմնորոշված ծրագրավորման հիմնական միջոց։

Փորձեցի մաթեմատիկական արտահայտությունների օրինակով գրել մի կարճ ծրագիր՝ օգտագործելով հենց այդ TclOO ընդլայնումը։ Այս օրինակս ընդհանուր պատկերացում տալիս է դասերի, կոնստրուկտորների, մեթոդների ու դաշտերի դահմանման մասին։

Եվ այսպես, նախ սահմանեմ expression աբստրակտ դասը, որը ներկայացնում է միակ evaluate մեթոդը։
oo::class create expression {
  method evaluate {} {}
}
Այստեղ oo::class հրամանի create ենթահրամանով սահմանվում է դասը։ method հրամանով սահմանվում են դասի մեթոդները (այն շատ նման է proc հրամանին)։

Որպես expression աբստրակտ դասի առաջին ընդլայնում սահմանեմ number դասը։ Նշելու համար, որ այն expression դասի ընդլայնում է (ենթադաս է), օգտագործվել է superclass հրամանը՝ արգումենտում expression դասի անունով։
oo::class create number {
  superclass expression
  variable value
  constructor { v } {
    my variable value
    set value $v
  }
  method evaluate {} {
    my variable value
    return $value
  }
}
variable հրամանով հայտարարվում են դասի դաշտերը։ Այս դասի համար ես նախատեսել եմ թվի արժեքը ներկայացնող value դաշտը։ constructor հրամանով սահմանվում է դասի կոնստրուկտորը։ Այն ստանում է արգումենտների ցուցակ և կոնստրուկտորի մարմինը։ Դասի մեթոդներում, ինչպես նաև կոնստրուկտորում դասի դաշտերը (փոփոխականները) մատչելի են դառնում my հրամանով։ "my variable value" տողը հնարավորություն է տալիս կոնստրուկտորի մարմնում աշխատել value փոփոխականի հետ։ number դասի համար իրականացված evaluate մեթոդը պարզապես վերադարձնում է value փոփոխականի արժեքը։

expression դասի երկրորդ ընդլայնումը ունար գործողությունները մոդելավորող unaryex դասն է։ Սրա կոնստրուկտորը ստանում է ունար գործողության նշանակումը և այն ենթաարտահայտությունը, որի վրա պետք է կիրառել գործողությունը։
oo::class create unaryex {
  superclass expression
  variable oper subex
  constructor { op ex } {
    my variable oper subex
    set oper $op
    set subex $ex
  }
  method evaluate {} {
    my variable oper subex
    set res [$subex evaluate]
    if {$oper eq "-"} {
      set res -$res
    }
    return $res
  }
}
evaluate մեթոդը նախ հաշվում է ենթաարտահայտության արժեքը, ապա, եթե գործողությունը "-" է, վերադարձնում է արժեքի բացասումը։

Եվ վերջապես, expression դասի մի ընդլայնում ևս։ Սահմանեմ binaryex դասը, որը մոդելավորում է բինար "+", "-", "*", "/" և "%" գործողությունները։
oo::class create binaryex {
  superclass expression
  variable oper subex0 subex1
  constructor { op exo exi } {
    my variable oper subex0 subex1
    set oper $op
    set subex0 $exo
    set subex1 $exi
  }
  method evaluate {} {
    my variable oper subex0 subex1
    set res0 [$subex0 evaluate]
    set res1 [$subex1 evaluate]
    set result 0
    switch $oper {
      "+" { set result [expr $res0 + $res1] }
      "-" { set result [expr $res0 - $res1] }
      "*" { set result [expr $res0 * $res1] }
      "/" { set result [expr $res0 / $res1] }
      "%" { set result [expr $res0 % $res1] }
    }
    return $result
  }
}
Այստեղ առանձնապես բացատրելու բան չկա. օգտագործված են Tcl լեզվի պարզագույն հրամաններ։

* * *
Դասերի հիերարխիան ստուգելու համար կազմեմ "(10 + 2 - 6) * 5 / -3" արտահայտության հաշվարկի ծրագիրը (որի արժեքը -10 է)։
proc example0 {} {
  # (10 + 2 - 6) * 5 / -3 = -10
  set n10 [number new 10]
  set n2 [number new 2]
  set n6 [number new 6]
  set n5 [number new 5]
  set n3 [number new 3]
  
  set u0 [unaryex new "-" $n3]
  
  set b0 [binaryex new "+" $n10 $n2]
  set b1 [binaryex new "-" $b0 $n6]
  set b2 [binaryex new "*" $b1 $n5]
  set b3 [binaryex new "/" $b2 $u0]
  
  set result [$b3 evaluate]
  return $result
}

* * *
Վերջում նշեմ, որ բոլոր փորձարկումներն արել եմ Tcl լեզվի ActiveTcl 8.6 իրականացմամբ։

No comments:

Post a Comment