2013-10-07 3 views
7

私は通常、「本能的」な方法で関数でプログラムを作成しますが、私の現在の問題はオブジェクトによって簡単に解決できるため、このメソッドを先に進めます。rebolにオブジェクトコンストラクタがあります

これを行うには、例えば、のinit()に相当するコンストラクタメソッドをオブジェクトに与える方法を見つけようとしています。

私はhttp://www.rebol.com/docs/core-fr/fr-index.htmlのドキュメントを見ましたが、関連するものは見つかりませんでした。

答えて

3

実は、(私は古き良きアドバイス続く:「フランスのマニュアルを読む」)を再びREBOLのコアのドキュメントを読むことによって、非常に簡単、コンストラクタを実装する別の方法があります:

http://www.rebol.com/docs/core-fr/fr-rebolcore-10.html#section-8

もちろん

それは英語のマニュアルでもある:

http://www.rebol.com/docs/core23/rebolcore-10.html#section-7

=>

自己変数を使用してのもう一つの例は、 自身のクローン機能である:

person: make object! [ 
    name: days-old: none 
    new: func [name' birthday] [ 
     make self [ 
      name: name' 
      days-old: now/date - birthday 
     ] 
    ] 
] 

lulu: person/new "Lulu Ulu" 17-May-1980 

print lulu/days-old 
7366 

私は、これは非常に便利見つけ、そしてこのように、コンストラクタはオブジェクト内にあります。この事実は、オブジェクトをより自立させる。

私は成功し、いくつかの地質学的なもののため、それがうまく機能が実装:

>> source orientation 
orientation: make object! [ 
    matrix: [] 
    north_reference: "Nm" 
    plane_quadrant_dip: "" 
    new: func [{Constructor, builds an orientation object! based on a measurement, as given by GeolPDA device, a rotation matrix represented by a suite of 9 values} m][ 
     make self [ 
      foreach [a b c] m [append/only matrix to-block reduce [a b c]] 
      a: self/matrix/1/1 
      b: self/matrix/1/2 
      c: self/matrix/1/3 
      d: self/matrix/2/1 
      e: self/matrix/2/2 
      f: self/matrix/2/3 
      g: self/matrix/3/1 
      h: self/matrix/3/2 
      i: self/matrix/3/3 
      plane_normal_vector: reduce [matrix/1/3 
       matrix/2/3 
       matrix/3/3 
      ] 
      axis_vector: reduce [self/matrix/1/2 
       self/matrix/2/2 
       self/matrix/3/2 
      ] 
      plane_downdip_azimuth: azimuth_vector plane_normal_vector 
      plane_direction: plane_downdip_azimuth - 90 
      if (plane_direction < 0) [plane_direction: plane_direction - 180] 
      plane_dip: arccosine (plane_normal_vector/3) 
      case [ 
       ((plane_downdip_azimuth > 315) or (plane_downdip_azimuth <= 45)) [plane_quadrant_dip: "N"] 
       ((plane_downdip_azimuth > 45) and (plane_downdip_azimuth <= 135)) [plane_quadrant_dip: "E"] 
       ((plane_downdip_azimuth > 135) and (plane_downdip_azimuth <= 225)) [plane_quadrant_dip: "S"] 
       ((plane_downdip_azimuth > 225) and (plane_downdip_azimuth <= 315)) [plane_quadrant_dip: "W"] 
      ] 
      line_azimuth: azimuth_vector axis_vector 
      line_plunge: 90 - (arccosine (axis_vector/3)) 
     ] 
    ] 
    repr: func [][ 
     print rejoin ["Matrix: " tab self/matrix 
      newline 
      "Plane: " tab 
      north_reference to-string to-integer self/plane_direction "/" to-string to-integer self/plane_dip "/" self/plane_quadrant_dip 
      newline 
      "Line: " tab 
      rejoin [north_reference to-string to-integer self/line_azimuth "/" to-string to-integer self/line_plunge] 
     ] 
    ] 
    trace_te: func [diagram [object!]][ 
     len_queue_t: 0.3 
     tmp: reduce [ 
      plane_normal_vector/1/(square-root (((plane_normal_vector/1 ** 2) + (plane_normal_vector/2 ** 2)))) 
      plane_normal_vector/2/(square-root (((plane_normal_vector/1 ** 2) + (plane_normal_vector/2 ** 2)))) 
     ] 
     O: [0 0] 
     A: reduce [- tmp/2 
      tmp/1 
     ] 
     B: reduce [tmp/2 0 - tmp/1] 
     C: reduce [tmp/1 * len_queue_t 
      tmp/2 * len_queue_t 
     ] 
     L: reduce [- axis_vector/1 0 - axis_vector/2] 
     append diagram/plot [pen black] 
     diagram/trace_line A B 
     diagram/trace_line O C 
     diagram/trace_line O L 
    ] 
] 
>> o: orientation/new [0.375471 -0.866153 -0.32985 0.669867 0.499563 -0.549286 0.640547 -0.0147148 0.767778] 
>> o/repr 
Matrix:  0.375471 -0.866153 -0.32985 0.669867 0.499563 -0.549286 0.640547 -0.0147148 0.767778 
Plane: Nm120/39/S 
Line: Nm299/0 

この方法のもう一つの利点は、(「新しい」方法で定義された変数は、直接オブジェクト「インスタンス」に属することです私はいくつかの問題に遭遇しました。他の方法では、自己/時には、変数を初期化する必要があるかどうかについて言及する必要があります)。

6

REBOLの中には特別なコンストラクタ関数はありませんが、あなたは仕様ブロック内のオブジェクトの作成時に、それを必要とする場合アドホック初期化コードを記述する可能性があります。たとえば:あなたはベースオブジェクトに慣例により、独自の「コンストラクタ」関数を定義するのであれば

a: context [x: 123] 

b: make a [ 
    y: x + 1 
    x: 0 
] 

、あなたは、作成上のスペックブロックを呼び出すことができます。渡された引数の可能な衝突を避けるだろう

a: context [ 
    x: 123 
    init: func [n [integer!]][x: n] 
] 

new-a: func [n [integer!]][make a [init n]] 

b: new-a 456 

より堅牢な(しかし、少し長い)バージョン:あなたはそれを自動化したい場合は、このように、機能であることをラップすることができますオブジェクト自身の言葉でのinit に次のようになります。

new-a: func [n [integer!] /local obj][ 
    also 
     obj: make a [] 
     obj/init n 
] 

ます。また、最初の引数としてベースオブジェクトを取得し、自動的にCLON後コンストラクタバイ規則機能を呼び出します。より一般的な新しい機能を書くことができしかし、オプションのコンストラクタ引数を一般的な方法でサポートするのは、もっと難解です。

はREBOLののオブジェクトモデルはプロトタイプベース(Pythonや他のほとんどのOOP言語でクラスベースの対)であるので、「コンストラクタ」機能は、が作成された各新しいオブジェクトのを重複して取得することを覚えておいてください。膨大な数のオブジェクトを作成する場合は、このようなコストを避けたいかもしれません。

+0

はい、どちらも非常に似た解決策になります。 initまたはnew?それはコンストラクタメソッドに名前を付けるための質問です... もちろん、大量のオブジェクトを生成する場合は、このようなメソッドは絶対に避けてください。私の現在の問題では、実際にいくつかのオブジェクトを考えていました。 – Pierre

5

私の知る限り、init()のようなオブジェクトコンストラクタを使用するための正式な方法/規約はありません。構築派生オブジェクトの組み込みの方法はもちろんあります:

make prototype [name: "Foo" description: "Bar"] 
    ; where type? prototype = object! 

私の最高の提案は、その後の方法、ここではそのような機能だと適用され、コンストラクタメソッドのオブジェクトを検査関数を定義するだろうと私[proposed previously VEの:

new: func [prototype [object!] args [block! none!]][ 
    prototype: make prototype [ 
     if in self 'new [ 
      case [ 
       function? :new [apply :new args] 
       block? :new [apply func [args] :new [args]] 
      ] 
     ] 
    ] 
] 

使用は非常に簡単である:

thing: context [ 
    name: description: none 
    new: [name: args/1 description: args/2] 
] 

derivative: new thing ["Foo" "Bar"] 
012:プロトタイプオブジェクトは new値を有する場合、それは誘導体オブジェクトの構築に適用されます

このアプローチはRebol 2と3の両方で機能することに注意してください。

+0

ok:必要な場合は、オブジェクト内のコンストラクタメソッドの適切な規則です。 – Pierre

3

私は、OOがどのようにREBOLで動作するかを調べようとしています。確かにプロトタイプです。

;---- First instance, created from its class ----; 
this-object: THIS-CLASS/.new 1 
print invoke this-object 'add [2] 

;---- Second instance, created from from a prototype ----; 
that-object: this-object/.class/.new 2 
print invoke that-object 'add [4] 

;---- Third instance, created from from a prototype in another way ----; 
yonder-object: invoke that-object '.new [3] 
print invoke yonder-object 'add [6] 

;---- Fourth instance, created from from a prototype in a silly way ----; 
silly-object: yonder-object/.class/.class/.class/.class/.new 4 
print silly-object/.class/add 8 silly-object 
print this-object/.class/add 8 silly-object 
print THIS-CLASS/add 8 silly-object 

(それはREBOL 2で動作し、そして:そして、あなたがこれを行うことができます

;---- Generic function for class or instance method invocation ----; 
invoke: func [ 
    obj [object!] 
    fun [word!] 
    args [block!] 
][ 
    fun: bind fun obj/.class 
    ;---- Class method names start with a dot and instance method names don't: 
    unless "." = first to-string fun [args: join args obj] 
    apply get fun args 
] 

;---- A class definition ----; 
THIS-CLASS: context [ 
    .class: self       ; the class refers to itself 

    ;---- Class method: create new instance ----; 
    .new: func [x' [integer!] /local obj] [ 
     obj: context [x: x' .class: none] ; this is the object definition 
     obj/.class: self/.class   ; the object will refer to the class 
              ; it belongs to 
     return obj 
    ] 

    ;---- An instance method (last argument must be the instance itself) ----; 
    add: func [y obj] [ 
     return obj/x + y 
    ] 
] 

:昨日、私は、機能の重複することなく、以下の古典的なオブジェクト指向のモデルを私に触発され、このページに出くわしました3,6,9,12,12,12を連続して印刷します。)オーバーヘッドはほとんどありません。多分他の解決策を見つけるのは難しくありません。正確にそれが本当の問題です:それを行うには余りにも多くの方法があります。 (たぶん、LoyalScriptのほうがいいかもしれません)

関連する問題