インスタンスメソッドとクラスメソッドの違いに入門してみる その2
インスタンスメソッドとクラスメソッドの違いに入門してみるのその2になります。
前回のエントリは下記からご覧ください。
今回は、selfキーワードやらクラスの継承やらをメモに残しておきます。
selfキーワードに関して
インスタンスの呼び出し
Rubyにはselfキーワードというものがあります。selfはインスタンス自身を表すキーワードです。
以下のコードは、selfなしでnameメソッドを呼び出す場合、self付きでnameを呼び出す場合、直接インスタンス変数を呼び出す場合の3つを試しています。
class User attr_accessor :name #インスタンスメソッド def initialize(name) @name = name end def hello # selfなしでnameメソッドを呼び出す puts "Hello, I am #{name}." end def hi # self付きでnameメソッドを呼ぶ puts "Hi, I am #{self.name}" end def my_name # 直接インスタンス変数へアクセス puts "My name is #{@name}" end end user = User.new('Alice') user.hello user.hi user.my_name #=> Hello, I am Alice. #=> Hi, I am Alice #=> My name is Alice
これはどれも正解です。人によって書き方が異なるでしょう。
ただし、変数を書き換えたり、name=メソッドで呼び出す場合はselfの有無でエラーが起きるので注意が必要です。
クラスメソッドをインスタンスメソッドを呼び出す
実はクラスメソッドをインスタンスメソッドを呼び出すことができます。
クラス名.メソッド
で呼び出すことができます。
クラスの継承
Rubyではクラスを作成すると継承することができます。 上位のクラスをスーパークラスと呼び、継承をする側をサブクラスと呼びます。
クラスを継承する場合は、下記のように書きます。
class subclass < superclass end
また、クラスを継承した場合は、アクセサメソッドを省略することができます。
class Product attr_accessor :name,:price def initialize(name,price) @name = name @price = price end end product = Product.new('a great movie',1000) product.name product.price #クラスを継承する class DVD < Product #nameとpriceはスーパークラスでattr_accessorが設定されているので定義不要 attr_accessor :running_time def initialize(name,price,running_time) @name = name @price = price @running_time = running_time end end dvd = DVD.new('a great movie',1000,120) dvd.name dvd.price dvd.running_time
またいちいちinitializeを定義しなくても、superメソッドを使うとそのまま利用することができます。
class DVD < Product #省略 def initialize(name,price,running_time) super(name,price) @running_time = running_time end end
メソッドの公開レベル
privateメソッドについて
Rubyのメソッドにはpublicメソッドとprivateメソッドがあります。
privateメソッドは、クラスの外からは呼び出せず、クラスの内部でのみ利用できるメソッドだと言えます。
class User def initialize(my_name) @my_name = my_name end #ここから下はprivateメソッド private def hello puts 'Hello' end end user = User.new('Bob') user.hello #=> エラー
メソッドレベルを後から変更
実はpublicメソッドで定義したメソッドを後からprivateメソッドに変更することも可能です。
class User #publicメソッドとして定義 def foo puts 'foo' end def bar puts 'bar' end #公開レベルを変更する private :foo, :bar #bazはpublicメソッド def baz puts 'baz' end end
また他のオブジェクトでは使いたいけど、一般公開したくない場合はprotectedメソッドというのもあります。 それぞれの用途に合わせて使い分ける必要があるでしょう。
変数について
最後はクラスインスタンス変数とクラス変数について紹介します。
インスタンスメソッドとクラスメソッドがあるように、変数にも2種類存在します。
クラスインスタンス変数
クラスインスタンス変数は、インスタンスの作成とは無関係にクラス自身が保持しているデータを表します。
class Product # クラスインスタンス変数 @name = 'Product' def self.name #クラスインスタンス変数 @name end def initialize(name) #インスタンス変数 @name = name end def name #インスタンス変数 @name end end
クラスインスタンス変数は、スーパークラスとサブクラスに別々の内容が管理されます。これはクラス自身にデータを管理させるという管理方法を再諾しているからです。
クラス変数
Rubyにはクラスメソッド内でもインスタンスメソッド内でも共有され、なおかつスーパークラスとサブクラスでも共有される変数も存在します。
それがクラス変数で、@@から始めるのが特徴です。
class Product @@name = 'Product' def self.name @@name end def initialize(name) @@name end def name @@name end end class DVD < Product @@name = 'DVD' def self.name @@name end def upcase_name @@name.upcase end end #DVDクラスを定義した時点で、@@nameがDVDに変更される Product.name #=> "DVD" DVD.name #=> "DVD"
それぞれの変更状況などを見て、使い分ける必要がありそうです。