日別アーカイブ: 2021年11月3日

Rubyのまとめ5(クラスから継承まで)

4から続きます

クラス

オリジナルのクラスを作成する例:箱を定義するクラス
Boxクラス
メソッド hello ・・・ helloと出力する機能

class Box
  def hello
    puts 'hello'
  end
end

box = Box.new
box.hello

hello
class Box
  def initialize(name)
    puts 'initialize'
    @name = name 
  #インスタンス変数はインスタンス内であればどこでも使える
  #↑逆にこれは他では使えない
 end   

  def hello
    puts "Hello! I am #{@name}."
  end 
end

box = Box.new('Cardboard')
box.hello

wood = Box.new('wood')
wood.hello

#.rbで出力すると
initialize
Hello! I am wood.

更にインスタンスを追加することもできる

class Box
  def initialize(name)
    puts 'initialize'
  @name = name
end
  def hello
    puts "Hello! I am #{@name}."
  end
end

box = Box.new('Cardboard')
box.hello
wood = Box.new('wood')
wood.hello

#.rbで出力すると
initialize
Hello! I am Cardboard.
initialize
Hello! I am wood.

アクセサメソッド:インスタンス変数の値を読み書きするメソッドのこと

class Box
  def initialize(name)
    @name = name
  end
  def hello
    puts "Hello! I am #{@name}."
  end

  def name
    @name
  end
end

box = Box.new('Cardboard')
puts box.name

#.rbで出力すると
initialize
hello! I am Cardboard.
Cardboard

クラスの外からnameメソッドでインスタンス変数を呼び出した

インスタンス変数の@nameの値をクラスの外から書き換えたい

class Box
  def initialize(name)
    @name = name
  end
  def hello
    puts "Hello! I am #{@name}."
  end

  def name
   @name
  end
end
box = Box.new('Cardboard')
puts box.name
#.rbで出力すると
Cardboard
box.@name = 'suzutuki'
↑Syntax error インスタンス変数は外から書き換えられない

ではどうするか?書き込み用のメソッドを作る

class Box
  def initialize(name)
    # puts 'initialize'
  @name = name
  end
  def hello
    puts "Hello! I am #{@name}."
  end

#他の言語だとゲッターメソッド
  def name
    @name
  end
#他の言語だとセッターメソッド
  def name=(value) #←ここから
    @name = value
  end
end

box = Box.new('Cardboard')
# box.hello
puts box.name
box.name = 'suzutuki'
puts box.name

#.rbで出力すると
Cardboard
suzutuki

name=のように=で終わるメソッドを定義すると
変数に代入するような形でメソッドが呼び出される。
box.name = 'suzutuki'という書き方ができるようになる
メソッドを呼び出しているけれども
値('suzutuki')を代入するような書き方ができる。

インスタンス変数を読み書きするメソッドのことを
インスタンスメソッドと呼ぶ
設定を書き換えたいとき

アクセサメソッドattr_accessorメソッド
attrはattributeで属性のこと
インスタンスメソッドを開発者が書かなくて良くなる

class Box

attr_accessor :name
  def initialize(name)
    puts 'initialize'
    @name = name
  end
  def hello
    puts "Hello! I am #{@name}."
  end

# def name
#   @name
# end

# def name=(a)
#   @name = a
# end
end

box = Box.new('Cardboard')

puts box.name

box.name = 'suzutuki'
puts box.name

↓ruby accessor.rbで出力
Cardboard
suzutuki

class Box
  attr_accessor :name
end

box = Box.new
puts box.name
box.name = 'suzutuki'
puts box.name

#.rbで出力すると

suzutuki
※空欄はnilで初期引数を指定しないとなる

コメントアウトしているところを1行で書くことができる
定型文的なメソッドを毎回書かなくて良いので開発を効率化できる

読み込みのみしたいとき

class Box

attr_reader :name
  def initialize(name)
    @name = name
  end
  def hello
    puts "Hello! I am #{@name}."
  end

# def name
#   @name
# end

# def name=(a)
#   @name = a
# end
end

box = Box.new('Cardboard')
# box.hello
puts box.name
# box.name = 'suzutuki'書き込みをしようとするとエラーになる
puts box.name

↓ruby accessor.rb
Cardboard
Cardboard

↑書き込みがされてないので2回Cardboardが出力された
なお書き込もうとするとエラーが出る↓
accessor.rb:26:in `<main>': undefined method `name=' for #<Box:0x00000000021c7df0 @name="Cardboard"> (NoMethodError)
Did you mean? name

書き込みのみしたいとき

class Box

attr_writer :name
  def initialize(name)
    @name = name
  end
  def hello
    puts "Hello! I am #{@name}."
  end

# def name
#   @name
# end

# def name=(a)
#   @name = a
# end
end

box = Box.new('Cardboard')
# box.hello
# puts box.name
box.name = 'suzutuki'
# puts box.name

#.rbで出力すると
何も起きてないように見えるが書き込みはされている。表示はされない

クラス変数:クラス自体に値を保持できる変数

class Box

@@count = 0
  def initialize(name)
    @name = name
    @@count += 1
  end

  def hello
    puts "Hello! I am #{@name}. #{@@count} instance(s)."
  end
end

kit = Box.new('Cardboard')
kit.hello

wood = Box.new('wood')
wood.hello

suzutuki = Box.new('suzutuki')
suzutuki.hello

#.rbで出力すると
Hello! I am Cardboard. 1 instance(s).
Hello! I am wood. 2 instance(s).
Hello! I am suzutuki. 3 instance(s).

クラスメソッドinfoを定義、クラスメソッドinfoを実行すると
インスタンスの生成回数(@@count)を出力する

class Box

@@count = 0
  def initialize(name)
    @name = name
    @@count += 1
  end

  def hello
    puts "Hello! I am #{@name}. #{@@count} instance(s)."
  end

  def self.info
    puts "#{@@count} instance(s)."
  end
end

Box.info
#.rbで出力すると
0 instance(s).

↑インスタンスの生成が行われていないので0
class Box
  
@@count = 0
  def initialize(name)
    @name = name
    @@count += 1
  end
  
  def hello
    puts "Hello! I am #{@name}. #{@@count} instance(s)."
  end

  def self.info
    puts "#{@@count} instance(s)."
  end
end

kit = Box.new('Cardboard')
Box.info

wood = Box.new('wood')
Box.info

suzutuki = Box.new('suzutuki')
Box.info

#.rbで出力すると
1 instance(s)
2 instance(s)
3 instance(s)

一つのクラス変数@@countをそれぞれのインスタンスが共通して
利用していることがわかる

class FF
  def self.first_method
    puts '1'
  end

  class << self
    def second_method
     puts '2'
    end
    
    def third_method
      puts '3'
    end
   end
end

FF.first_method
FF.second_method
FF.third_method

#.rbで出力すると
'1'
'2'
'3'

FF.new.varだとエラー
オブジェクトからクラスメソッドを呼び出そうとしてもエラーになる

 

クラスと定数

class Box
REGION = 'USA'
@@count = 0
  def initialize(name)
    @name = name
    @@count += 1
  end

  def hello
    puts "Hello! I am #{@name}. #{@@count} instance(s)."
  end
  
  def self.info
    puts "#{@@count} instance(s). Region: #{REGION}"
  end
end

kit = Box.new('Cardboard')
Box.info

wood = Box.new('wood')
Box.info

suzutuki = Box.new('suzutuki')
Box.info

puts Box::REGION
クラスの外から呼び出せる

#.rbで出力すると
1 instance(s). Region: USA
2 instance(s). Region: USA
3 instance(s). Region: USA
↓putsがあるので4番目のUSAも出力されている。ないと3行まで
USA

クラスの継承

親クラスを作成することで親クラスの機能を引き継いで、
子クラスを作成することができる。
コードの再利用性や拡張性を高める仕組み

#親クラスのUserを作る
class User
  def initialize(name)
    @name = name
  end
  
  def hello
    puts "Hello! I am #{@name}"
  end
end

akina = User.new('akina')
akina.hello
#.rbで出力すると
Hello! I am akina
class AdminUser < User
#子クラスまたはサブクラスを作った
  def hello_admin
    puts "Hello! I am #{@name} from AdminUser."
  end
end
suzutuki = AdminUser.new('suzutuki')
suzutuki.hello
suzutuki.hello_admin

#.rbで出力すると
Hello! I am akina
Hello! I am suzutuki
Hello! I am suzutuki from AdminUser.

 

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

  def hello
    puts "Hello! I am #{@name}"
  end
end

#子クラスまたはサブクラスを作った
class AdminUser < User
  def hello_admin
    puts "Hello! I am #{@name} from AdminUser."
  end
#↓helloメソッドをAdminUserの方でオーバーライドする
  def hello
    puts 'Admin!!'
  end
end

suzutuki = AdminUser.new('suzutuki')
suzutuki.hello
suzutuki.hello_admin

#.rbで出力すると
Admin!!
Hello! I am suzutuki from AdminUser.

親クラスから小クラスのメソッドは呼び出せないのに注意!

子クラスを編集することにより親クラスに変更を加えることなく
子クラスに機能を追加したり上書き(オーバーライド)することができる!

class User
 def initialize(name)
   @name = name
 end
 def hello
   puts "Hello! I am #{@name}"
 end
end

class AdminUser < User
 def hello_admin
   puts "Hello! I am #{@name} from AdminUser."
 end
 #↓helloメソッドをAdminUserの方でオーバーライドする
 def hello
   super
   puts 'Admin!!'
 end
end

suzutuki = AdminUser.new('suzutuki')
suzutuki.hello
akane = AdminUser.new('akane')
akane.hello

#.rbで出力すると

Hello! I am suzutuki
Admin!!
Hello! I am akane
Admin!!

親クラスのUserクラスのhelloも呼び出されている!

Integerの継承関係から継承関係を見ることができる

BasicObject
↑
Object
↑
Numeric
↑
Integer
#superclassで親クラスを知ることができる
Integer.superclass
=> Numeric
2.5.1 :002 > Numeric.superclass
=> Object
2.5.1 :003 > Object.superclass
=> BasicObject
2.5.1 :004 > BasicObject.superclass
=> nil

6に続く