This page is intended for users in Germany. Go to the page for users in United States.

Ruby Koansを初心者文系が解いていく2 - classについて

はじめまして、ダイアモンドヘッド札幌に入社予定の伊藤です。今は研修課題でRuby Koans(http://rubykoans.com/)に取り組んでいます。

私はデータ処理のために大学で少しpythonを使う程度で、classを活用した事が無かったためclassに関する問題でかなり苦労しました。

その中でも以下の問題(204番)を解決するのに一番時間がかかったので振り返りがてら記事にします。

問題

以下は問題204番のコードです。

class Dog7
attr_reader :name
def initialize(initial_name)
@name = initial_name
end
def get_self
self
end
def to_s
@name
end
def inspect
"<Dog named '#{name}'>"
end
end
def test_inside_a_method_self_refers_to_the_containing_object
fido = Dog7.new("Fido")
fidos_self = fido.get_self
assert_equal __, fidos_self
end

下から2行目のassert_equalの次の「__」に正しい答えを書くと次に進めます。問題中で定義されたDog7を読み、その挙動を考えていきます。

問題の解説

まずはクラス定義から読んで行きます。

  1. attr_readerはインスタンス変数のゲッターです。
  2. initializeメソッドはオブジェクトが作成される時に自動的に呼び出されます。ここでは新しいオブジェクトを作ったときに、引数を@nameに格納します。@のついた変数をインスタンス変数といい、同じインスタンス内であればメソッドを超えて扱えます。
  3. get_selfはselfを返します。ここが最後まで分からなかった箇所なので後述。
  4. to_sメソッドは、普通はオブジェクトを文字列にして返すメソッドですが、ここではnameを返すものとして定義しています。
  5. inspectは一般に、オブジェクトをわかりやすい文字列にして返します。#<クラス名:0x16進数 @インスタンス変数名=値,
    ...>という文字列が返ります。ここではそれを上書きして、<Dog named '#{name}'>を返すように定義しています。

次に問題となっている test_inside_a_method_self_refers_to_the_containing_object の中身を見ていきます。

  1. fidoにDog7の新しいインスタンスを格納しnameは'Fido'とします。
  2. 次はfidos_selfに.get_selfでselfを代入します。
  3. そしてfidos_selfとは何かを調べて答えるという問題です。

解答

Ruby Koansは毎回ヒント(というか答え?)を貰えます。

$ Expected "FILL ME IN" to equal <Dog named 'Fido'>

これに従い、"<Dog named 'Fido'>"と回答しましたが、正解ではないようです。

しばらく悩んでもわからなかったのでGoogleで調べて見ると以下のstackoverflowが見つかりました、同じ事を考えている人がいるものですね。
https://stackoverflow.com/questions/32666702/ruby-koans-quest-203about-classes-failed-with-rake

これによると答えはfidoです。

それを踏まえてコードを見なおしてみると、selfはインスタンスそのものを返すのだろうという予想ができます。

二つのobject idを表示してみると
$ fido : 14576340, fidos_self : 14576340

同じidだということが分かります。ということはfido==fidos_selfであり、答はfidoとなります。

Koansはゲーム感覚で問題に取り組み、知らないうちに少しずつ理解が深まる良い教材だと思います。

これらも頑張って取り組んで行きます!

おまけ

ここで一つ疑問だったのが「なぜヒントが<Dog named 'Fido'>なのか」という点です。その答えはassert_equalの定義にありました。

以下、neo.rbにあるassert_equalの定義です。

def assert_equal(expected, actual, msg=nil)
msg ||= "Expected #{expected.inspect} to equal #{actual.inspect}"
assert(expected == actual, msg)
end

2行目を見ると、メッセージとしてオブジェクトのinspectを表示する仕様になっています。

だからヒントにはDog7クラスで定義したinspectの内容が表示される仕組みなのです。

ダイアモンドヘッド株式会社s Stellenangebote
Anonymous
1936352 1062127003862239 5929320466037171604 n
8354fd80 d21d 4ae0 84df c61be22325a8?1512456374
1256501 410509932393905 1175023648 n
Anonymous
29063454 1847953721884383 1542633187639820288 n
6 Likes
Anonymous
1936352 1062127003862239 5929320466037171604 n
8354fd80 d21d 4ae0 84df c61be22325a8?1512456374
1256501 410509932393905 1175023648 n
Anonymous
29063454 1847953721884383 1542633187639820288 n
6 Likes

Wöchentliches Ranking

Weitere Rankings anzeigen

Page top icon