1

Ruby で変数の機能を拡張したいと考えています。その理由は、型システムまたは値チェッカーに似たものに取り組んでいるためです (これは少しクレイジーに聞こえますが、全体のアイデアは説明するのが長すぎます。デフォルト変数を拡張したいという理由だけです)。

私は、Ruby ではすべてがオブジェクトであることを読みました。したがって、変数はオブジェクトです。また、Ruby は、メタプログラミングによって変更できる内容に関して、非常に寛大であると考えられています。

拡張できるローカル変数に関連付けられたある種の「クラス」はありますか?

型の文字列表現を保持する変数ごとに文字列変数を関連付けたいと思います。さらに、変数の割り当てをインターセプトし、新しい値が変数に割り当てられるたびにメソッドを実行したいと考えています。これは、新しい値が型 (変数に文字列として格納されている) に従って正しいかどうかを確認できるようにするためです。

Ruby のローカル変数がクラスのオブジェクトとして定義されている場合、そのクラスを拡張したり、Ruby mixin を介して変更したりできます。

回避策は、変数の新しいクラスを作成することです (Ruby のローカル変数でビルドを使用しないでください)。このクラスには、値属性、型の属性 (文字列として格納)、および get メソッドと set メソッドを含めることができます。このようにして問題を解決できますが、可能であれば、Ruby の組み込み変数を拡張したいと考えています。

現在進行中の作業

class Fixnum
        attr_accessor :tp
        @tp

        def mytype ( type )
                @tp = type
        end
        def typecheck
                #call typechecker
                puts "checked"
        end
end

テストコード:

a = 3
a.mytype("nat")
puts a.tp
a.typecheck

まだ2つの問題があります。 まず、Fixnum に新しいコンストラクターを追加することはできないと思います。次に、変数アクセスをインターセプトしたいと思います。つまり、「b = a」は a のメソッド「typecheck」を呼び出します。しかし、これにはアスペクト指向プログラミングに似たものが必要であり、これが Ruby のメタプログラミング機能で解決できるかどうかはわかりません。

4

3 に答える 3

4

Rubyでは、すべてがオブジェクトであることを読みました

それは、「オブジェクト」とすべての「もの」の定義によって異なります。「オブジェクト」とは、「プログラムによって操作できるエンティティ」(これからオブジェクトと呼びます)、または「オブジェクト システムのメンバーである値」 (これから呼びます) を意味Objectします。

Ruby では、プログラムによって操作できるすべてのもの (つまり、すべてのオブジェクト) はObject、クラスのインスタンスでもあります。これは、たとえば、プリミティブをプログラムで操作できる (つまり、その意味でのオブジェクトObjectsである) Java とは異なりますが、そうではありません。Ruby では、この区別は存在しません。すべてのオブジェクトは でありObject、すべてはオブジェクトObjectでもあります。

ただし、言語には、プログラムで操作できず、クラスのインスタンスではないものがあります。つまり、オブジェクトでもオブジェクトでもありません。たとえば、メソッド、変数、構文、パラメーター リスト、引数リスト、キーワードなどです。Object

注: Ruby のリフレクション API を使用して、メソッドまたはパラメーター リストを表すオブジェクトを提供できますが、そのオブジェクトは単なるプロキシであり、本物ではありません。

したがって、「すべてがオブジェクトである」と言うとき、本当の意味は、「すべてのオブジェクトがオブジェクトであるObject」ということです。つまり、プログラムによって操作できるものはすべて、オブジェクト システムのメンバーでもあるということです。 (Java のプリミティブとは異なり) オブジェクト システム外の値ではありません。言語に存在するすべてのものが実行時にプログラムによって操作できるという意味ではありません。

したがって、変数はオブジェクトです

いいえ、残念ながら、それらはオブジェクトでもオブジェクトでもありませんObject

これは、Ruby言語仕様にも明確に記載されています(強調は私が追加しました):

6.2 変数

6.2.1 一般的な説明

変数は名前で示され、変数の値と呼ばれるオブジェクト を参照します。変数自体はオブジェクトではありません

Matz と David Flanagan による「The Ruby Programming Language 」の2 ページに次のように書かれています。

すべての値はオブジェクトです

すべてを表しているわけではなく、すべての値のみを表していることに注意してください。

Is variable is object in ruby​​?という質問も参照してください。

于 2012-08-27T18:20:23.987 に答える
1

できることがいくつかあります。手始めに、すべての (またはほぼすべての) Ruby クラス (数値などの「プリミティブ」を含む) は、オブジェクトの文字列表現を返す to_s メソッドをサポートしています。数値の場合、to_s はその数値の文字列表現を返します (たとえば、42 の場合は "42")。他のクラスで返される文字列値は異なります。良いことは、「モンキーパッチ」を介してクラスのメソッドをオーバーライドできることです。非常に不自然な例を次に示します。

class Array
  def to_s
    return "An array of size #{self.size}."
  end
end

a = [1, 2, 3, 4]
puts a.to_s
# => "An array of size 4."

変数の値が設定されるたびにメソッドを実行することに関する他の質問については、これを処理する方法は、アクセサー メソッドを介して常に変数と対話することです。このようにして、プロパティの getter および setter メソッド内にカスタム コードを実装できます (または単にアクセサー内から別のメソッドを呼び出します)。このような:

class MyClass
  # Use the default getter for var.
  attr_reader :var      

  def initialize
    @var = 1
  end

  # Custom setter for var.
  def var= v
    @var = v
    puts "var changed to #{v}"
  end
end

mc = MyClass.new
mc.var = 9
# => "var chaged to 9"
于 2012-08-27T18:38:04.783 に答える
0

次のようなこともできますが、グローバルに対してのみ機能します。

$type_checked = {:$a => String, :$b => Array}
$type_checked.keys.each do |var|
  trace_var(var) do |obj|
    puts "hey, don't assign #{var} to a #{obj.class}" unless $type_checked[var] == obj.class
    #or raise an Error
  end
end

$a = 1
$a = "a"
$b = 1

#output:
#hey, don't assign $a to a Fixnum
#hey, don't assign $b to a Fixnum

しかし、これは明らかに言語の性質に反します。

于 2012-08-27T18:53:53.750 に答える