RubyのStructクラスが便利

特にちょっとしたデータ構造を作成したいときなんかは非常に有効な手段かも

Structクラス


Rubyの組み込みクラスです。(Classに比べて影が薄いですが・・・)

平たく言うと、Classクラスに似ているものです。

じゃー違いは何なの?ってなります。

  1. newしたとき、引数で指定したアクnセッサをもつクラスを生成する
  2. 第一引数の文字列がクラス名となるが、指定がない場合は無名のクラスになる

これだけ。

1
2
3
4
Point = Struct.new("Point", :x, :y)
item = Point.new(100,200)
p item => #<struct Struct::Point x=100, y=200>
p item.x => 100

無名クラスだと、こんな感じ

1
2
3
4
Point2 = Struct.new(:z)
Point2.class => Class
item2 = Point2.new(300)
p item2 => #<struct Point2 z=300>

ドキュメントに無い機能


ブロックを使うことができることです。
ブロック内では、独自のメソッドを定義することができます。

こんな感じです。

1
2
3
4
5
6
7
8
9
10
11
Point = Struct.new(:x, :y) do
  def sum
        x + y
  end

  def minus
        x - y 
  end
end
p Point.new(600, 700).sum => 1300
p Point.new(800,900).minus => -100

他にも、superを使うことで、上位のコンストラクタを実行することができます。

1
2
3
4
5
6
7
8
9
class Point < Struct.new(:x, :y)
  def initialize(x, y)
    z = x + y
    super(z, y)
  end
end

item = Point.new(400, 500)
p item => #<struct Point x=900, y=500>

使いどころ


正直、あんまり無いような気がしなくもないですが、自分だと以下で使います。

  • csvファイルとか読み込むとき、ちょっとしたデータ構造を定義するとき
  • ちょっとしたデータのソート
  • ちょっとしたアルゴリズムの追加
  • ハッシュの代わりとか(既にデータ構造が分かってる場合など)

データソートする場合の例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Point < Struct.new(:x, :y)
  def initialize(x, y)
    z = x + y
    super(z, y)
  end
end

item = Point.new(400, 500)
item2 = Point.new(200,300)

p item => #<struct Point x=900, y=500>
p item2 => #<struct Point x=500, y=300>

array = []
array << item
array << item2

p array => [#<struct Point x=900, y=500>, #<struct Point x=500, y=300>]

result = array.sort{ |item1,item2|
                    item1.x <=> item2.x
               }
p result => [#<struct Point x=500, y=300>, #<struct Point x=900, y=500>]

書き捨てみたいなRubyコードを書くときにはちょうどいいのかもしれないですね。