singleton method Struct.[]

new(*args, keyword_init: nil) -> Class[permalink][rdoc][edit]
new(*args, keyword_init: nil) {|subclass| block } -> Class

Struct クラスに新しいサブクラスを作って、それを返します。

サブクラスでは構造体のメンバに対するアクセスメソッドが定義されています。



dog = Struct.new("Dog", :name, :age)
fred = dog.new("fred", 5)
fred.age = 6
printf "name:%s age:%d", fred.name, fred.age
#=> "name:fred age:6" を出力します

実装の都合により、クラス名の省略は後づけの機能でした。メンバ名に String を指定できるのは後方互換性のためだと考えた方が良いでしょう。したがって、メンバ名は Symbol で指定するのが無難です。

[PARAM] args:
構造体を定義するための可変長引数。String または Symbol を指定します。
[PARAM] keyword_init:
構造体クラスのインスタンスを生成する際に、キーワード引数を使用するかどうかを指定します。値の意味は次のとおりです。
  • nil: キーワード引数と位置引数のどちらを使用してもよい
  • true: キーワード引数のみ使用できる
  • false: キーワード引数は使用できず、位置引数のみ使用できる


Point1 = Struct.new(:x, :y)
Point1.new(1, 2)             # => #<struct Point1 x=1, y=2>
Point1.new(x: 1, y: 2)       # => #<struct Point1 x=1, y=2>
Point1.new(x: 1)             # => #<struct Point1 x=1, y=nil>
Point1.new(y: 2)             # => #<struct Point1 x=nil, y=2>
Point1.new(x: 1, y: 2, z: 3) # => ArgumentError (unknown keywords: z)

Point2 = Struct.new(:x, :y, keyword_init: nil)
Point2.new(1, 2)             # => #<struct Point2 x=1, y=2>
Point2.new(x: 1, y: 2)       # => #<struct Point2 x=1, y=2>
Point2.new(x: 1)             # => #<struct Point2 x=1, y=nil>
Point2.new(y: 2)             # => #<struct Point2 x=nil, y=2>
Point2.new(x: 1, y: 2, z: 3) # => ArgumentError (unknown keywords: z)

Point3 = Struct.new(:x, :y, keyword_init: true)
Point3.new(1, 2)             # => wrong number of arguments (given 2, expected 0) (ArgumentError)
Point3.new(x: 1, y: 2)       # => #<struct Point3 x=1, y=2>
Point3.new(x: 1)             # => #<struct Point3 x=1, y=nil>
Point3.new(y: 2)             # => #<struct Point3 x=nil, y=2>
Point3.new(x: 1, y: 2, z: 3) # => ArgumentError (unknown keywords: z)

Point4 = Struct.new(:x, :y, keyword_init: false)
Point4.new(1, 2)             # => #<struct Point4 x=1, y=2>
Point4.new(x: 1, y: 2)       # => #<struct Point4 x={:x=>1, :y=>2}, y=nil>
                             # これは Point4.new({x: 1, y: 2}) とみなされていることに注意
Point4.new(x: 1)             # => #<struct Point4 x={:x=>1}, y=nil>
Point4.new(y: 2)             # => #<struct Point4 x={:y=>2}, y=nil>
Point4.new(x: 1, y: 2, z: 3) # => #<struct Point4 x={:x=>1, :y=>2, :z=>3}, y=nil>

第一引数が String の場合

args[0] が String の場合、クラス名になるので、大文字で始まる必要があります。つまり、以下のような指定はエラーになります。



p Struct.new('foo', 'bar')
# => -:1:in `new': identifier foo needs to be constant (NameError)

また args[1..-1] は、SymbolString で指定します。



p Struct.new("Foo", :foo, :bar)   # => Struct::Foo

第一引数が Symbol の場合

args[0] が Symbol の場合、生成した構造体クラスは名前の無いクラスになります。名前の無いクラスは最初に名前を求める際に代入されている定数名を検索し、見つかった定数名をクラス名とします。



Foo = Struct.new(:foo, :bar)
p Foo                             # => Foo

ブロックを指定した場合

Struct.new にブロックを指定した場合は定義した Struct をコンテキストにブロックを評価します。また、定義した Struct はブロックパラメータにも渡されます。



Customer = Struct.new(:name, :address) do
  def greeting
    "Hello #{name}!"
  end
end
Customer.new("Dave", "123 Main").greeting # => "Hello Dave!"

Structをカスタマイズする場合はこの方法が推奨されます。無名クラスのサブクラスを作成する方法でカスタマイズする場合は無名クラスが使用されなくなってしまうことがあるためです。

[SEE_ALSO] Class.new

new(*args) -> Struct[permalink][rdoc][edit]
self[*args] -> Struct

(このメソッドは Struct の下位クラスにのみ定義されています) 構造体オブジェクトを生成して返します。

[PARAM] args:
構造体の初期値を指定します。メンバの初期値は指定されなければ nil です。
[RETURN]
構造体クラスのインスタンス。
[EXCEPTION] ArgumentError:
構造体のメンバの数よりも多くの引数を指定した場合に発生します。


Foo = Struct.new(:foo, :bar)
foo = Foo.new(1)
p foo.values      # => [1, nil]