📔

思い出したい人のためのRuby入門 Class編

に公開

はじめに

この記事は、あとから振り返ったときに、なるべく短い時間で内容を復習できるようにするために書かれています。

丁寧な説明記事は、長い時間の中でたくさんの方が作ってくださっているので、この記事では丁寧さよりも、簡潔さと網羅性を優先します。

誰のための記事か

  • 過去にRubyを学習したが、忘れてしまって思い出したい人

誰のためではないか

  • Rubyを初めて学ぶ人
  • オブジェクト指向の考え方を知りたい人

コンストラクタ

class User
  def initialize(name, age)
    @name = name
    @age = age
  end
end

attr_xxx

classの外部から値を参照したり、変更したりするために用いる

attr_reader

  • getterが自動的に定義される
class User
  attr_reader :name, :age

  def initialize(name, age)
    @name = name
    @age = age
  end
end
alice = User.new("Alice", 30)
puts alice.age # 30

attr_writer

  • setterが自動的に定義される
class User
  attr_reader :name, :age

  def initialize(name, age)
    @name = name
    @age = age
  end
end
alice = User.new("Alice", 30)
alice.age = 31

attr_accessor

  • getterとsetterが自動的に定義される
class User
  attr_accessor :name, :age

  def initialize(name, age)
    @name = name
    @age = age
  end
end
alice = User.new("Alice", 30)
alice.age = 31
puts alice.age # 31

getter, setter

class User
  attr_accessor :name, :age

  def initialize(name, age)
    @name = name
    @age = age
  end

  def age=(new_age)
    @age = new_age
  end

  def age
    @age
  end
end
alice = User.new("Alice", 30)
alice.age = 31
puts alice.age # 31

変数と定数

インスタンス変数

  • @xxxで定義する
class User
  def initialize(name)
    @name = name
    @age = age
  end
end
alice = User.new("Alice")
bob = User.new("Bob")

クラス変数

  • @@xxxで定義する
class User
  @@count = 0 # 作成されたユーザ数
  
  def initialize()
    @@count += 1
  end
  
  def self.count
    @@count
  end
end
alice = User.new()
bob = User.new()
puts User.count #  2

定数

  • 大文字で定義する
class User
  MAX_AGE = 150

  attr_reader :age
  
  def initialize(name, age)
    @name = name
    @age = age if age <= MAX_AGE
  end
end
alice = User.new("Alice", 30)
p alice.age # 30
bob = User.new("Bob", 200) 
p bob.age # nil

メソッド

インスタンスメソッド

class User
  def initialize(name)
    @name = name
  end

  def print_profile
    puts "Name: #{@name}"
  end
end
alice = User.new("Alice")
alice.print_profile # Name: Alice

クラスメソッド

class User
  def self.create(name)
    new(name)
  end
end
alice = User.create("Alice")

継承

class Person
  attr_reader :name
  
  def initialize(name)
    @name = name
  end
  
  def greeting
    "Hello, I'm #{@name}"
  end
end

class User < Person
  attr_reader :age
  
  def initialize(name, age)
    super(name)
    @age = age
  end
end
alice = User.new("Alice", 30)
puts alice.greeting # Hello, I'm Alice
puts alice.age # 30

オーバーライド

class User < Person
  attr_reader :age
  
  def initialize(name, age)
    super(name)
    @age = age
  end

  def greeting
    "Hi! I'm #{@name}, #{@age} years old"
  end
end

alice = User.new("Alice", 30)
puts alice.greeting # Hi! I'm Alice, 30 years old
puts alice.age # 30

クラス変数

class Person
  @@species = "Homo sapiens"
  
  def self.species
    @@species
  end
end

class User < Person
end
puts User.species # Homo sapiens

クラス変数のオーバーライド

  • 親クラスのクラス変数も上書きされる
class Person
  @@species = "Homo sapiens"
  
  def self.species
    @@species
  end
end

class User < Person
  @@species = "HOMO SAPIENS"
end
puts Person.species # HOMO SAPIENS
puts User.species # HOMO SAPIENS

公開設定

public

  • 呼び出せる人:だれでも
class User
  public
  def public_method
    p "Public method"
  end
end
user = User.new
user.public_method # Public method

private

  • 呼び出せる人: privateメソッドを定義したクラスやサブクラスのインスタンス(クラスが同じでもインスタンスが違うと呼び出せない)
class User
  def public_method
    # インスタンス内からは呼び出せる
    private_method 
  end
  
  private
  
  def private_method
    "This is private"
  end
end
user = User.new
user.public_method # OK
user.private_method # private method 'private_method' called for an instance of User (NoMethodError)

サブクラスから呼び出すこともできる

class User
  def initialize(name)
    @name = name
  end
  
  private
  
  def format_name
    @name.upcase
  end
end

class AdminUser < User
  def display_name
    "Admin: #{format_name}"
  end
end
alice = AdminUser.new("Alice")
puts alice.display_name # Admin: ALICE

protected

  • 呼び出せる人: protectedメソッドを定義した同じクラスかサブクラスのインスタンス(インスタンスが違っても、クラスが同じなら呼び出せる)
class User
  def initialize(name, age)
    @name = name
    @age = age
  end

  def older_than?(other_user)
    # protectedメソッドは同じクラスやサブクラスのインスタンスから呼び出せる
    # age が private になっている場合、other_user から取得できない
    age > other_user.age 
  end
  
  protected

  # 年齢を公開しない
  def age
    @age
  end
end
alice = User.new("Alice", 30)
bob = User.new("Bob", 25)
puts alice.older_than?(bob) # true

self

selfが参照するものは、呼び出す場所によって変化する

クラス直下

class User
  # クラス定義直下のself → クラス自身
  puts self           # User
end

インスタンスメソッド内

class User
  def initialize(name)
    @name = name
  end
  
  # インスタンスメソッド内のself → インスタンス自身
  def instance_method
    puts self         # <User:0x00007f...>
    puts self.class   # User
  end
end

クラスメソッド内

class User
  def self.class_method
    puts self         # User
  end
end

セッターメソッド

セッターメソッドを呼び出すときには、必ずselfが必要
(ない場合は、ローカル変数として扱われる)

class User
  def initialize(name)
    @name = name
  end
  
  def update_name(new_name)
    self.name = new_name
  end
  
  # セッターメソッドを呼ぶ時はselfが必須
  def name=(new_name)
    @name = new_name
  end

  def name
    @name
  end
end
user = User.new("Alice")
user.update_name("Bob")
puts user.name # Bob

参考文献

Discussion