• WebCamp_インタビュー
    【WebCamp卒業生インタビュー】1ヶ月でRubyをゼロから学び、Webエンジニアとして転職!
    2018.01.15
  • WebCamp_インタビュー
    「1カ月頑張ればこの先が見えてくる」地元メディアを立ち上げたママさん
    2017.07.20
  • WebCampPro_インタビュー
    未経験でも寿司職人からWebデザイナーになった!ホスピタリティでスクールを支える宮脇トレーナー
    2017.05.26
  • WebCampPro_インタビュー
    未経験31歳からエンジニア転職を実現【実際に聞いてみた】
    2017.04.01
  • WebCampPro_インタビュー
    未経験から上京し、エンジニアとしてチームラボグループに転職!【WebCampPro卒業生インタビュー】
    2018.03.10
  • WebCamp_インタビュー
    「自信の持てるスキルを得たい!」内定辞退した女子大生がプログラミングを学習したワケ。
    2018.04.28
  • WebCamp_インタビュー
    “未経験”でもたった1ヶ月で営業からエンジニアとして転職!『WebCamp』受講者インタビュー
    2017.10.04
  • WebCampPro_インタビュー
    自分で稼ぐ力をつけるため、新卒5年目の営業マンがエンジニアに転職!【WebCampPro転職者インタビュー】
    2018.02.02
  • WebCamp_インタビュー
    【卒業生インタビュー】台湾で月間100万UUの訪日旅行メディアを手掛けるCEOが、プログラミングを学んで得たものとは?
    2018.01.15
  • WebCamp_インタビュー
    【WebCamp受講生インタビュー】起業準備中にCEOが気がついたプログラミングスキルの重要性とは?
    2017.12.25
  • WebCamp_インタビュー
    時間や場所にとらわれず自由に働くために必要なスキルとは?【WebCamp卒業生インタビュー】
    2018.01.26

◆当サイトで人気のプログラミング教室のおすすめランキングはこちら!
プログラミングは独学では非効率で、時間を無駄にするリスクがあります。効率的なカリキュラムで学べるスクールを受講しましょう。

Web Camp【マンツーマンサポート】1ヶ月短期集中でプログラミングを学ぶスクール
1ヶ月通い放題・メンター常駐の教室環境でWebサービス等作りたい方
TechAcademyオンラインで開講しているプログラミングスクール
オンラインでどこでも学べる!/教室に行くのが忙しい人でも安心!
Tech Camp教養としてのITスキルを学べるスクール
Webデザイン/AI(人工知能)/IOS/Androidアプリ制作/VRを学びたい方!
WebCampPro転職保証付き!エンジニアとして転職したい人におすすめ!
未経験からプロのエンジニアを3ヶ月で目指すプログラミングスクールです。
11月生募集中!当社人気の転職保証コース
プログラミング学習から転職成功まで導く、当社人気のWebCamp Proコース。
10月生は満員となっております。11月生募集に向け、お早めの申込みをオススメします。
プログラミング未経験でもエンジニア転職を絶対成功させたい
スキルを身に着けて人生を自ら切り開きたい
上記にあてはまる方は、ぜひご検討ください!

クラスは設計図です。

そして、インスタンスは設計図から作られた実態です。

+メソッドやto_sメソッドなどが定義されたIntegerクラスがあり、プログラム内でi = 1などとしたときにiという実態が生成されているわけです。

そんなクラスとインスタンスの関係、インスタンスと変数との関係を詳しく解説していきます。

なお、後半は少し踏み込んだ内容になっていますので、軽く読んで難しければ、しばらく学習した後で戻ってきていただいても良いかもしれません。

むしろ、その方がより理解が深まることでしょう。

Rubyのクラスとインスタンス

インスタンスというのは、クラスという設計図をもとに作られた「もの(オブジェクト)」です。

Rubyはオブジェクト指向言語ですので、オブジェクトを中心にして処理が進みます。つまり、Rubyプログラムはほとんどの場合、インスタンスが中心となって動いているのです。

現実世界でも、設計図や仕様書は存在しますが、実際に使っているのは、それらから作られた「もの」だというのは、分かると思います。

反面、クラスは設計図として「もの」を作った後に使われることはないのでしょうか?

もちろん、同じ「もの」を作るのに設計図は必須ですので、量産するにはかけがえのないものです。

Inst00-1.rb

class Test
  @@serial = 0

  def initialize
    @name = "Test" + @@serial.to_s
    @@serial += 1
  end

  def get_name
    return @name
  end
end

test_a = Test.new # ......(1)
test_b = Test.new
test_c = Test.new

puts(test_a.get_name)
puts(test_b.get_name)
puts(test_c.get_name)

Inst00-1.rbは、インスタンスを生成するたびにクラス変数@@serialに格納してあるシリアル番号を+1して@nameに付与するクラスです。

クラス変数はクラスに固有の変数ですので、Testクラスから生成されるインスタンスのインスタンス変数@nameに付与されるシリアル番号が+1されたものになるという仕組みになっています。

現実世界でも量産品にシリアル番号をつけることはありますが、それと同様なことが、クラスとインスタンスでも可能だということです。

クラスもオブジェクト

じつは、設計図であるクラスが、インスタンスを生成するとき以外に利用されることがないかというと、そういうわけでもありません。

クラスも「設計図」という「もの(オブジェクト)」ですので、設計図なりに値を参照されたりすることはあるのです。

現実世界であれば、購入時にカタログや仕様書を見て検討したり、修理やメンテナンスでは、設計図や仕様書をもとに正しい設定になっているかを確認したりするでしょう。それと同様に、クラスというオブジェクトを利用する場合もあります。

Rubyプログラムでは、「クラスオブジェクト」としてメソッドを使うことがあります。

具体的には、Inst00-1.rbの(1)のように、インスタンスを生成するときのnewメソッドは、すべてのクラスで「クラス名.new」の形で利用します。

これはつまり、Rubyでは、クラスもオブジェクトと解釈されていることです。

また、その他の代表的な例としては、Timeクラスでの現在時間の取得もクラスオブジェクトからnowメソッドを利用しています。

puts(Time.now)

クラスとインスタンスの関係

つまり、クラスとインスタンスは、現実世界の「設計図」と「もの」の関係と同じように、お互いオブジェクトとして密接な関係にあります。

むしろ、Rubyのクラスにおいては、インスタンスを作る予定のないクラスもありますので、よりクラスをオブジェクトとして扱う色が濃いと言えるでしょう。

「クラス=設計図」と「インスタンス=もの」という理解が強くなると、インスタンスを作る以外ではクラスが使われないようなイメージが生まれます。そうなると、Rubyの理解の妨げになってしまうのです。

Rubyのクラスとインスタンスは、インスタンスがクラスから生成されるということ以外、オブジェクトとしてはほぼ同等の関係だと思った方が良いでしょう。

時間や場所にとらわれず自由に働くために必要なスキルとは?【WebCamp卒業生インタビュー】
2018-01-26 13:03
今回の記事では、WebCampに1ヶ月間通い、未経験からエンジニアとして転職した星野さんにお話を伺いました。 <プロフィール> 星野 智洋 さん(25) 学生時代は日本大学芸術学部...

インスタンスと変数

クラスから生成されたインスタンスとプログラムの中で宣言する変数は、同じものです。

イメージとして、変数はただの箱であるようなイメージがあるかもしれませんが、Rubyの変数はオブジェクトであり、IntegerクラスやArrayクラスなどのインスタンスなのです。

その瞬間において、どう呼ぶかというだけで、まったく同じものだということは、理解しておきましょう。

インスタンス変数

インスタンスと変数は同じものですが、「インスタンス変数」というのは、それらとは別のものです。

【Ruby入門説明書】クラスの定義について解説でも簡単に説明していますが、メソッド内で利用されている「@」+変数名の変数のことで、インスタンス内で共有されている変数です。

つまり、インスタンス変数というのは、インスタンスが保持している値であり、メソッドはその値を操作するための道具だと考えると良いでしょう。

インスタンス変数へのアクセス(アクセサについて)

なんの工夫もしなければ、インスタンス変数へアクセスできるのは、そのインスタンスのメソッドだけです。(カプセル化の概念からすれば、当然でしょう)

そのため、Inst00-1.rbのget_nameメソッドのように、インスタンスの外から参照するためには、専用のメソッドを準備しなければいけません。

しかし、それでは利便性が悪い場合がありますので、Rubyには「アクセサ」という仕組みが備わっています。

用途に合わせて、以下のアクセサのいずれかを登録することで、インスタンス変数へアクセスするためのメソッドをわざわざ用意する必要がなくなります。

アクセサ 用途
attr_reader 参照のみ可能
attr_writer 変更(代入のみ)可能
attr_accessor 参照も変更も可能

設定するための文法は、以下のようにとても簡単です。

class クラス名

  アクセサ:インスタンス変数名,インスタンス変数名 ,,,

end

Inst00-1.rbを改造して、使い方も含めて動きを見てみましょう。

Inst00-2.rb

class Test
  @@serial = 0

  attr_reader:name # .......(1)

  def initialize
    @name = "Test" + @@serial.to_s
    @@serial += 1
  end
  
#  def get_name # ..........(2)
#    return @name
#  end

end

test_a = Test.new
test_b = Test.new
test_c = Test.new

# puts(test_a.get_name) # ..(3)
# puts(test_b.get_name)
# puts(test_c.get_name)
puts(test_a.name)
puts(test_b.name)
puts(test_c.name)

(1)で参照専用のアクセサを追加し、(2)のメソッドは不要ですので削除、(3)にあるメソッドでのアクセスを削除して、アクセサでのアクセスへと変更しています。

attr_writerやattr_accessorでも同じ記述で代入専用や参照と代入が可能なアクセサが設定でき、代入する場合は、以下のように単純な記述で行うことができます。

test_a.name = 10

このように、アクセサを使うことで、インスタンス変数へのアクセスをシンプルな記述で表現することが可能になります。

コツコツ独学×スクールで実践。未経験からエンジニアに転職!【WebCamp卒業生インタビュー】
2018-03-22 23:28
今回の記事では、独学でPHPを1年半学習し、その後WebCampを受講して未経験からエンジニアへと転職された佐々木さんにお話を伺いました。 <プロフィール> 佐々木 祐樹 さん(2...

クラスとインスタンスと変数とメソッド

ここからは、少し深い内容の説明をしていこうと思います。

といっても、ここまでに説明した内容で説明し切れていない部分を穴埋めする内容です。つまり、これまでの内容をより深く理解するという意味での深さですので、安心してください。ただし、サンプルプログラムも長く案っていますし、説明も概念的になっていますので、少し難しいと感じたのであれば、あとで読み直すなどしても構いません。自分のペースで進めていきましょう。

まずは、<リンク>【Ruby入門説明書】クラスの定義について解説にあるclass00-1.rbを以下のように改造して実行してみましょう。

Inst01-1.rb

# 計算機クラス
class Calc

  puts("計算機クラスの試作")

  @@memory = 0 # ...........................(1)
  
  # 初期化
  def initialize(name = "calc")
    @name = name
    cl
  end

  # 足し算
  def inc(val)
    temp = @result
    @result += val
    disp("inc", temp.to_s, val.to_s)
  end

  # 引き算
  def dec(val)
    temp = @result
    @result -= val
    disp("dec", temp.to_s, val.to_s)
  end

  # 初期化
  def cl
    temp = @result
    @result = 0
    disp("Init", temp.to_s, "0")
  end

  # 結果表示
  def disp(method, last_ret = "", val = "", result = @result)
    puts("#{@name}.#{method}(#{val}): #{last_ret} --> #{result}")
  end

  private :disp  # dispをprivateにする


  # メモリー機能の追加
  # メモリーを足す  # .......................(2)
  def inc_mem
    print("[inc_mem]")
    inc(@@memory)
  end

  # メモリーを引く  # .......................(3)
  def dec_mem
    print("[dec_mem]")
    dec(@@memory)
  end

  # メモリーを設定  # .......................(4)
  def set_mem
    temp = @@memory
    @@memory = @result
    disp("set_mem", temp.to_s, @result, @@memory.to_s)
  end

  # メモリーをクリア  # .....................(5)
  def cl_mem
    temp = @@memory
    @@memory = 0
    disp("cl_mem", temp.to_s, "", @@memory.to_s)
  end

  # 計算機能の追加
  @self_ret = 0 # ...........................(6)

  # 足し算 # ................................(7)
  def self.inc(val)
    @self_ret += val
    return @self_ret
  end

  # 引き算 # ................................(8)
  def self.dec(val)
    @self_ret -= val
    return @self_ret
  end

  # 初期化 # ................................(9)
  def self.cl
    @self_ret = 0
  end

  # 結果出力 # ..............................(10)
  def self.disp
    return @self_ret
  end
end

# 計算機インスタンスを生成
calc1 = Calc.new("calc1")
calc2 = Calc.new("calc2")

# calc2にのみ、かけ算メソッドを追加
# かけ算
def calc2.mul(val) # .......................(11)
  temp = @result
  @result *= val
    disp("mul", temp.to_s, val.to_s)
end

# 計算
calc1.inc(5)
calc1.set_mem # ............................(12)
calc1.dec(3)
puts
calc2.inc_mem # ............................(13)
calc2.cl_mem # .............................(14)
calc2.mul(2) # .............................(15)
puts
calc1.dec_mem # ............................(16)
# calc1.mul(2) # ...........................(17)
puts
#Calcクラスの計算機能を利用
puts("#Calcクラスの計算機能を利用")
puts("Calc.inc(7) : #{Calc.disp} + 7 = #{Calc.inc(7)}") # .....(18)
puts("Calc.dec(5) : #{Calc.disp} - 5 = #{Calc.dec(5)}") # .....(19)
puts("Calc.disp   : #{Calc.disp}") # ..........................(20)

(結果)

計算機クラスの試作
calc1.Init(0):  --> 0
calc2.Init(0):  --> 0
calc1.inc(5): 0 --> 5
calc1.set_mem(5): 0 --> 5
calc1.dec(3): 5 --> 2

[inc_mem]calc2.inc(5): 0 --> 5
calc2.cl_mem (): 5 --> 0
calc2.mul (2): 5 --> 10

[dec_mem]calc1.dec(0): 2 --> 2

#Calcクラスの計算機能を利用
Calc.inc(7) : 0 + 7 = 7
Calc.dec(5) : 7 - 5 = 2
Calc.disp   : 2

ベースである計算機クラスに、メモリー機能(M+、M-、MRといったボタンで表現されている機能です)とかけ算機能、純粋な計算だけを行う機能を追加しています。

追加機能それぞれについて、変数とメソッドの動きがポイントとなりますので、詳しく説明していきましょう。

変数

ここで追加したのは、ただのメモリー機能ではありません。クラス変数を使った、複数のインスタンスで共有できるメモリー機能なのです。

クラス変数を使っているため、calc1インスタンスとcalc2インスタンスの@@memoryは共通のものになっています。そのため、calc1でセット(Inst01-1.rbの(7))された値をcalc2で使う(Inst01-1.rbの(18))ことができます。

また、計算機能追加用に、インスタンスには影響されない変数とメソッドが追加されています。これら(6)から(10)の変数とメソッドは、インスタンスからはアクセスできず、クラスからのみ利用が可能です。

つまり、この改造によって、このクラスは4種類の変数を使っていることになります。

変数については、すでに【Ruby入門説明書】クラスの定義について解説で簡単に説明していますが、改めてInst01-1.rbをもとに整理しておきましょう。

種別 説明 文法 Inst01-1.rb上の変数名
ローカル変数 それぞれのメソッドの中だけで存在しており、メソッドの処理が終了すると失われてしまう変数です。そのため、incメソッド実行後に他のメソッドなどでtempを参照しようとしても、エラーになります。 通常の変数通り incメソッドやdecメソッドにある、変数temp
インスタンス変数 インスタンスに属する変数で、インスタンスの中からであれば、どのメソッドからでも参照・変更できます。
インスタンスごとに作られる変数ですので、インスタンスごとに違う値を保持しています。
インスタンス生成後、最初に代入された時点で生成されますが、メソッド内でしか生成できませんので、注意が必要です。
変数名の前に「@」 @result
クラス変数 クラスで共通の変数として生成されますので、同じクラスから生成されたインスタンスすべてで共通の値を持つことになります 変数名の前に「@@」 @@memory
クラスインスタンス変数 クラスメソッド(後述)からのみアクセスできる変数で、メソッド内ではなく、クラス定義内に定義しなければいけません。クラスが定義されると同時に生成され、クラス変数同様、1つのクラスで共通の値を持っています 変数名の前に「@」 @self_ret

メソッド

Inst01-1.rbの(16)で、calc2インスタンスにだけ、かけ算を行えるmulメソッドを追加しています。

calc2インスタンスにだけ追加していますので、calc1で使用しようとするとエラーが発生します。そのため、(17)はコメントアウトしているわけです。

変数のときと同じように、これで計算機クラスは2種類のメソッドを持っていることになります。それぞれについて、まとめておきます。

種別 説明 文法 Inst01-1.rb上のメソッド名
インスタンスメソッド クラス内で定義されているが、インスタンスからしか利用できないメソッドです。 通常のメソッド通り incメソッド、decメソッドなど
特異メソッド クラス内で定義した場合は、クラスオブジェクトからのみ使用できるクラスメソッドになります。
クラス外で定義した場合は、特定のインスタンスに後からメソッドを定義することができます
メソッド名の前にオブジェクトを追加します mulメソッド

以上が、Inst01-1.rbで使用されているメソッドです。

インスタンスメソッドについては、特筆すべきことはありません。Rubyで作るメソッドのほとんどは、インスタンスメソッドになりますので、一般的にメソッドと言えばインスタンスメソッドのことを指します。

Inst01-1.rbのポイントは、この「特異メソッド」です。

特異メソッドを活用することで、メソッドの追加や、newメソッドやTimeクラスのnowメソッドのような、「インスタンスを不要とするメソッド」であるクラスメソッドを作ることができるのです。

もう少し詳しく説明するために、特異メソッドの文法を紹介しておきましょう。

def オブジェクト名.メソッド名
  処理
end

基本的には通常のメソッド定義と違いはありませんが、メソッドの名の前にこのオブジェクトを利用するオブジェクトを明示しておく点が違っています。

この明示するオブジェクトによって、その動きが大きく違っていますので、それぞれ説明しましょう。

メソッドの追加

オブジェクトとして、インスタンスを記載することで、そのインスタンスにメソッドを追加することができます。

クラスは、カプセル化によって閉じた世界になっていますので、あまりこの処理は推奨されませんが、自分が必要とする処理がない場合や、あっても細かな調整が必要な場合などには、プログラム全体の可読性を考慮して利用するのも悪くはありません。

ただし、頻繁に使いすぎると、可読性を極めて悪化させます(既存のメソッドなのかどうかの区別かつかない、など)。また、なにより再利用するときに、「クラスを再利用しようとしたら、じつは特異メソッドだった」ということが発生して再利用性も損ないますので、使いすぎには注意が必要です。

クラスメソッド

オブジェクトの部分にクラスを記載しているのが、クラスメソッドです。

Inst01-1.rbでは、selfになっていますが、特殊変数selfは、現在、どのオブジェクトの配下にあるかを保持している変数ですので、selfにはCalcクラスが格納されているわけです。

ほとんどの場合はクラス定義の中で定義されており、インスタンスがなくても機能を提供できるクラスを定義することができます。

インスタンス不要でも利用できるメソッドを提供する意味はいろいろとありますが、以下のような理由が考えられます。

・値を1つ取得するだけの処理(Timeクラスのnowメソッドなど)
・その瞬間にだけ必要で、その後利用することがほとんどない処理(Inst01-1.rbの計算処理など)
・インスタンスを生成する前段階で必要な処理(newメソッドなど)

最後の理由で作る場合は仕方ありませんが、その他の理由については、クラス定義を作成する段階では予測しにくいことがほとんどです。そのため、クラスメソッドで作ったものの、インスタンスから利用したくなることも少なくありませんので、無理にクラスメソッドを作る必要はないでしょう。

“未経験”でもたった1ヶ月で営業からエンジニアとして転職!『WebCamp』受講者インタビュー
2017-10-04 10:26
今回の記事では、未経験からWebCampを1ヶ月受講し、その後エンジニアとして転職をした喜田さんにお話を伺いました。 <プロフィール> 喜田 大介 さん (28歳) 大学時代はプ...

まとめ

インスタンスと変数について、説明しました。

特にインスタンスの扱い方やインスタンス変数について、クラスとの関係など、少し深い内容になっていましたので、イメージしにくかったかもしれません。

また、Inst01-1.rbはいままでにない行数のプログラムでしたので、少々難解に見えたとも思います。

しかし、これらの内容は、これからRubyプログラムの学習を進め、中級プログラマーになるためには、必ず通らなければならない部分ですので、何度も読んで理解を深めていただけることを祈ります。

概念的な説明も多いこういった部分は、やはり文字ではなく対面で人に教えてもらう方が明らかに理解が良いです。もし、機会があればスクールなどで質問してみると、効率が良いかもしれません。

・インスタンスは、クラスという設計図をもとに作られた「もの(オブジェクト)」
・クラスも「設計図」という「もの(オブジェクト)」
・インスタンス変数は、インスタンスの持っている値であり、メソッドはその値を操作するためのもの
・クラス変数はクラスが持っている値
・クラスインスタンス変数はクラスメソッドからのみアクセスできるクラスが持っている値
・インスタンスメソッドは、一般的なメソッドのことで、インスタンスからのみ利用できる
・インスタンス特有の特異メソッドを作ることで、インスタンスメソッドを追加できる
・クラス特有の特異メソッドは、クラスメソッドとなり、インスタンスがなくても使える

WebCampOnline プログラミングコースについて

WebCampでは、「どこでも学べる」オンラインコースを開講しています。

初心者・未経験の方でもわずか1ヶ月でプログラミングの基礎を学び、アプリケーション開発をすることができます。

WebCampOnlineが選ばれる3つの理由

1.学習の仕方がわからなくても安心!初心者に寄り添った学習カリキュラム

これから学習を始める初心者の方や、独学で挫折してしまった方に向けて、アプリケーション作成をゴールとする一気通貫したカリキュラムを提供しています。2500名を輩出しているWebCampだからこその教室でのリアルな受講生の声を反映し、オンラインコースでも初心者に寄り添った学習体験をご提供いたします。

2.つまずいたらすぐ解決!プロのエンジニアに質問し放題

プログラミング学習で挫折する理由の多くは「つまずいた時に聞ける人がいない」ことです。オンラインコースでは、現役エンジニアやプロ講師に、すぐにチャットでの質問が可能です。つまずきをすぐに解消できるので、挫折せずに学習を継続することができます

3.1ヶ月間で終わらなくても大丈夫!カリキュラムは"卒業後"も"無料"で利用可能

受講したいけど、仕事が急に忙しくなるかもしれないから受講するか迷っている・・・そんな方も多いのではないでしょうか?ご安心ください。カリキュラムは期間終了後も「無料」で使うことができます。また、しっかり学習時間を確保した方も、振り返って学習することでプログラミングスキルがご自身に馴染んできます。

▼まずは無料でWebデザインのカリキュラムを体験しよう!

【インタビュー】1ヶ月でRubyをゼロから学び、Webエンジニアとして転職!

ブラジルから帰国し技術をつけようとRubyエンジニアを目指してWebCampでRubyを学び、見事Webエンジニアとして転職を果たした田中さんにお話を伺いました。

Rubyの学習がしたい。基礎をしっかりと理解したい

転職のサポートがほしい

と考えている方はぜひお読み下さい。

【WebCamp卒業生インタビュー】1ヶ月でRubyをゼロから学び、Webエンジニアとして転職!
2018-01-15 13:23
今回の記事では、WebCampで1ヶ月間Rubyを学習し、Webエンジニアとして転職した卒業生の田中さんにお話を伺いました。 <プロフィール> 田中 デニス 昭彦さん(...
関連キーワード
Rubyの関連記事
  • 【Ruby入門説明書】rescueについて解説
  • 【Ruby入門説明書】jsonについて解説
  • 【Ruby入門説明書】csvについて解説
  • 【Ruby入門説明書】mapについて解説
  • 【Ruby入門説明書】gemsについて解説
  • 【Ruby入門説明書】ruby sliceについて解説
おすすめの記事