🐭

Ruby クラス②

2023/02/10に公開

クラスメソッド、クラス変数

クラスメソッド、クラス変数

クラスメソッド

  • クラスから直接呼ぶことができるメソッド

クラス変数

  • クラス自体に値を保持することができる変数

サンプルコード

class User
  REASION = 'USA'
  @@count = 0
  
  def initialize(name)
    @name = name
    @@count += 1
  end 
  
  def hello
    puts "I am #{@name}. #{@@count} instance(s)."
  end 
  
  def self.info
    puts "#{@@count} instance(s).Reasion: #{REASION}"
  end 
  
end 

emma = User.new('Emma')
#emma.hello
User.info
olivia = User.new('Olivia')
#olivia.hello
User.info
mary = User.new('Mary')
#mary.hello
User.info

puts User::REASION

👇

クラス変数は@@で始まる!

@@count = 0

initializeメソッドにも記述
initializeメソッドが呼ばれた回数
(インスタンスが作成された回数)をカウントする

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

そして、helloメソッドの中で出力

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

このように表示される

I am Emma. 1 instance(s).
I am Olivia. 2 instance(s).
I am Mary. 3 instance(s).

インスタンスを生成するために
このクラス変数の@@countがインクリメントされて
123というようになっている

次にクラスメソッドを定義する

クラスメソッドにはselfをつける

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

クラスメソッドはクラスから直接呼ぶことができる

インスタンスを作成しなくても

User.info

とすればクラスメソッドを呼び出すことができる

クラスで定数を定義する方法

慣習で定数名は大文字で書く

REASION = 'USA'

この定数をクラスメソッドで引用してみる

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

実行するとこのように出力されている

1 instance(s).Reasion: USA
2 instance(s).Reasion: USA
3 instance(s).Reasion: USA

定数はクラスの外からアクセスすることもできる

その場合このように記述する

puts User::REASION

REASIONに入っている定数USAが出力された

1 instance(s).Reasion: USA
2 instance(s).Reasion: USA
3 instance(s).Reasion: USA
USA

クラスの継承

クラスの継承

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

例)
【親】自動車クラス(タイヤ、エンジン、ブレーキ)

  • 【子】戦車クラス(+大砲)
  • 【子】乗用車クラス(+後部座席)
  • 【子】トラック(+荷台)

サンプルコード

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

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

end

nakamura = User.new('Nakamura')
nakamura.hello

class AdminUser < User
  def hello_admin
    puts "Hello! I am #{@name} form AdminUser."
  end
  
  def hello
    puts 'Admin!!'
  end
end

sato = AdminUser.new('Sato')
sato.hello
sato.hello_admin

👇

ユーザークラスを継承して、

Adminユーザークラス(管理者用のクラス)を作る

記述の仕方
class 子クラスの名前 < 親クラスのクラス名

class AdminUser < User
end

これでAdminユーザークラスはユーザークラスが持っている
インスタンス変数@nameやインスタンスメソッドhelloを利用できる

用語としてUserクラスの方を親クラス、またはスーパークラス
AdminUserクラスの方を子クラス、またはサブクラスと呼ぶ

AdminUserクラスの方にAdminUser専用のメソッドを書いてみる

(Userクラスに変更を加えずにAdminUser用の処理を追加できる)

class AdminUser < User
  def hello_admin
    puts "Hello! I am #{@name} form AdminUser."
  end

hello_adminメソッドをよび実行

sato.hello_admin

このように呼び出すことができる

Hello! I am Nakamura
Hello! I am Sato
Hello! I am Sato form AdminUser.

メソッドのオーバーライド

子クラスの方で親クラスの同じ名前のメソッドを上書きする方法

親クラスのhelloメソッドをAdminユーザーの方で
オーバーライドしてみる

  def hello
    puts 'Admin!!'
  end

親クラスのhelloメソッドではなく
子クラスでオーバーライドしたhelloメソッドの方が呼ばれた

Admin!

メソッドのアクセス権

メソッドのアクセス権

  • メソッドにアクセスできる条件を指定できる

3つの種類がある

  • public
    クラスの外部からでも自由に呼び出せる(デフォルト)
  • protected
    (※あまり使わないので今は省略)
  • private
    クラスの外からは呼び出せず、クラス内部でのみ使えるメソッド

サンプルコード

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

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

user = User.new('Nakamura')
user.hello

アクセス権を何も指定しない場合はpublicの指定となる
initializeメソッドは特別なメソッドなのでこの条件からは外れる

privateの指定をする

helloメソッドのアクセス権をprivateにするには
privateと上に書く

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

privateと書いた行よりも下に書いたメソッドは
アクセス権がpraivateになる

出力しても
NoMethodErrorとなる

モジュール

モジュール
クラスのようにメソッドや定数をまとめられるもの

クラスとの違い

  • インスタンスを作ることができない
  • 継承ができない

モジュールの定義

module モジュール名
 # モジュールの定義(メソッドや、定数など)
end

関連するメソッドや定数などをまとめてグループ化したいだけのときに
モジュールは手軽に使えて便利!

サンプルコード

module Driver
  def self.run
    puts 'Run'
  end

def self.stop
  puts 'Stop'
end
end

Driver.run
Driver.stop

インスタンスメソッドは作れないのでselfをつける

このようにメソッドを呼び出して出力できた

Run
Stop

#NG

#インスタンス化できない
driver = Driver.new

#継承もできない
module TaxiDriver < Driver
end

エラーになる

例外

例外(Exception)
プログラムの実行中に発生した「例外」的な問題

例外処理
例外が発生したときに、それをキャッチして、ユーザーにメッセージを表示するなど
何らかの処理を行うこと

数値を0で割った時の例外をキャッチして
例外処理としてエラーメッセージを出力するプログラムを書いてみる

今回はターミナルから数値を入力させるプログラムも書く

サンプルコード

puts '---数値を入力してださい---'
i = gets.to_i

begin
   # 例外が起きうる処理
puts 10 / i
rescue => ex
  # 例外が発生した場合の処理
  puts 'error!'
  puts ex.message
  puts ex.class
ensure
  # 例外が発生しても、しなくても、最後に実行したい処理
   puts 'end'
end

getsでターミナルに入力された文字列を取得できる

i = gets.to_i

その文字列をto_iメソッドで数値に変換
それを変数iに入れる

例外が起きうる処理

実行したい処理は

puts 10 / i

iに0が入った時は0除算となり、例外が発生する!!

例外処理を書くにはまずbeginとし、最後はend
beginの直下には例外が起きうる処理を書く
次にrescueを利用

rescue => ex

例外が発生した場合の処理を書く

  puts 'error!'
  puts ex.message
  puts ex.class
ensure

入力したユーザーにエラーを伝える puts 'error!'
エラーの内容が何なのか出力 puts ex.message
例外のオブジェクトのクラス名を知りたいとき puts ex.class
最後に ensure

例外が発生しても、しなくても、最後に実行したい処理を書く

puts 'end'

実行
10/2で5が出力された
ensureの処理でendも出力された

---数値を入力してださい---
2
5
end

エラーの場合

0
error!
divided by 0
ZeroDivisionError
end

エラーの内容
divided by 0 = 0で割ったのでエラーになっている
ZeroDivisionError = というクラス
最後にensure = end

実務では、このように例外が発生した場合の記述が大事になってくる!!

Rubyのコーディングルール(コーディング規約)

  • Rubyの公式のコーディングルールは存在しない(2017年1月現在)
  • 「The Ruby Style Guide」が有名
  • 参考:Rubyのソースコード解析ツールRuboCopの作者と同じ
    https://github.com/rubocop/rubocop

「リンク」
英語
https://github.com/rubocop/ruby-style-guide
日本語訳
https://github.com/fortissimo1997/ruby-style-guide/blob/japanese/README.ja.md

ここに書かれていることを全て守らなくてはいけないということではないが
プロジェクトチームで開発を行うときは
このコーディングルールをベースとして開発を行うと良い!

分量が多いので全てを覚えて確認をするのは大変

そこで同じ作者がRuboCopという
ソースコードを解析するツールを公開している

これを使うと開発したコードが自動でコーディングルールに
乗っ取っているか確認してくれる😃


Ruby一旦講座の範囲は終わり!!
明日からMySQL入る!
パワー

Discussion