6

たとえば、私が持っている場合

def function(arg)
  #do stuff
end

arg配列のみを許可するにはどうすればよいですか?私はそれをできた

def function(arg)
  if arg.class != 'Array'
    return 'Error'
  else
    #do stuff
  end
end

しかし、これを行うためのより良い方法はありますか?

4

6 に答える 6

11

他の言語では同じようにはできませんが def function(Array arg)、2 番目のスニペットの 4 行を 1 行に置き換えることができます。

def function(arg)
  raise TypeError unless arg.is_a? Array
  # code...
end
于 2012-05-30T21:14:54.643 に答える
6

あるタイプの引数を技術的に強制する方法を指摘する人もいますが、Ruby の考え方との根本的な戦いを戦っています。「ダックタイピング」でググってみてください。

ruby の世界では、通常、引数の型は気にしませんが、それを使ってやりたいことのインターフェイスに合っているかどうかを気にします。つまり、アヒルのように鳴きますか?十分です!

何かに Array を使用しようとしているとします。

def function(arg)
  arg.each do |a|
    puts a
  end
end

これを次のように呼び出すと、次のようfunction(1)になります:NoMethodError: undefined method 'each'

強制的に配列にするというあなたのアイデアを使用しましょう。

def function(arg)
  raise TypeError unless arg.is_a? Array
  arg.each do |a|
    puts a
  end
end

さて、これで別のエラーが発生しましたが、メソッドが配列以外で呼び出された場合でもエラーが発生します。

さらに、これはどうですか?

function("Hello World".chars)

おっと、関数が機能していたにもかかわらず、エラーが発生しました!

ルビーの方法は、次のようになります。

def function(arg)
  if arg.respond_to? :each
    arg.each do |a|
      puts a
    end
  else
    puts arg
  end
end

これで、関数はあらゆる種類の入力に対して適切に機能します。

function([1,2,3,4])
function("foo")
function("foo".chars)

関数の正確性については、コンパイラではなくテストを使用してカバーします。しかし、それはまったく別の主題です。:)

于 2012-05-30T21:50:16.093 に答える
2

Ruby は動的に型付けされることを考慮して、C のような同様の方法でそれを強制することはできません。文字列と比較する代わりに、実際にクラスと比較することができます。

arg.is_a?(Array)

あなたの例を改善するために、私は書いたでしょう:

 def function(arg)
   raise TypeError unless arg.is_a?(Array)
   # Do stuff
 end
于 2012-05-30T21:14:36.597 に答える
1

Ruby は型チェックをサポートしていません。少なくとも、メソッド シグネチャの一部として引数の型を宣言できるという意味ではサポートしていません。一般に、呼び出し元が正しいオブジェクトを渡す責任があるか、渡されたオブジェクトが自分自身を変換する責任があります。ただし、確かに独自の強制を行うことができます。実際、about.com には、この種の型チェックを行うための case ステートメントの使用例があります。

いくつかの追加の例を次に示します。

# Ask your object to convert itself to an array.
def foo my_object
  my_object.to_a
end

# Give your object a #to_a method if it doesn't already have one.
def foo my_object
  unless my_object.respond_to? :to_a
    def my_object.to_a
      # perform your type conversion
    end
  end
end

# Do your own type conversions.
def foo my_object
  case my_object
  when Array
    p my_object
  when String
    my_object.scan /\d+/
  end
end

これらの手法はどれでも組み合わせることができ、他にも確かに存在します。Ruby は非常に柔軟な言語です。

于 2012-05-30T21:49:16.350 に答える
0

例のレシーバーが自明であり、メソッドではなく関数のように定義されている場合は、引数をレシーバーに変換することをお勧めします。

class Array
  def function
    # do stuff
  end
end
于 2012-05-31T04:54:14.917 に答える
0

エラーを発生させる代わりに、引数を配列に変換することを確認できますが、最初に配列が得られるように、パラメーターを提供するルーチンで作業する必要があります。

def function(*arg)
  a = arg.flatten
  p a
end

function("ab")
function(1,2)
function([1,2])

#=>
#["ab"]
#[1, 2]
#[1, 2]
于 2012-05-30T22:27:46.970 に答える