なんだかGoodVibes

日々の勉強メモです。

【Ruby】[超入門] クラスメソッドを定義する

こんにちは。
本日はRubyメモです。

クラスメソッドとは?

クラスメソッドは、クラスに対して呼ぶメソッドで、
インスタンスを必要としません。

インスタンスメソッドは、インスタンスを必要とします。

本記事では、クラスメソッドの定義の仕方を

  • 特異メソッドを1つずつ定義する方法
  • 特異クラスを開いてまとめて定義する方法

を記載しています。


特異メソッドを1つずつ定義する方法

self.xxxと記載すると、特定のオブジェクトにxxxという
特異メソッドを1つ追加するという意味になります。

特異メソッドとは、特定のオブジェクト固有のメソッドのことです。

以下の例は、ItemInfoshow_countshow_name
という特異メソッドを追加しています。

class ItemInfo
    # クラス変数
    @@count = 0

    # コンストラクタ
    def initialize(id:, name:)
        @@count += 1

        @id = id
        @name = name
    end

    # インスタンスメソッド
    def show
        puts "ID = #{@id}, NAME =#{@name}"
    end

    # クラスメソッド
    def self.show_count
        puts "count = #{@@count}"
    end

    def self.show_name
        puts "ItemInfo"
    end
end

クラスメソッドを呼び出す際は以下のようにします。

ItemInfo.show_count
ItemInfo.show_name
# count = 1
# ItemInfo


特異クラスを開いてまとめて定義する方法

特異クラスとは、簡単に言うと「クラスオブジェクト専用のメソッド」の入れ物のようなものです。
class << selfでそのクラスオブジェクトの特異クラスを開き、
クラスメソッドをまとめて定義することができます。

先ほどのクラスを特異クラスを使用して書き換えると以下のようになります。

class ItemInfo
    # クラス変数
    @@count = 0

    # コンストラクタ
    def initialize(id:, name:)
        @@count += 1

        @id = id
        @name = name
    end

    # インスタンスメソッド
    def show
        puts "ID = #{@id}, NAME =#{@name}"
    end

    # 特異クラスを開いてクラスメソッドを定義
    class << self
        def show_count
            puts "count = #{@@count}"
        end

        def show_name
            puts "ItemInfo"
        end
    end
end

先ほどは、self.show_countself.show_nameと定義していましたが
特異クラスを開いて定義する場合、self.は記載不要となります。

呼び出し方法も同じです。

ItemInfo.show_count
ItemInfo.show_name
# count = 1
# ItemInfo


privateなクラスメソッドを定義する

privateなクラスメソッドとは、外部からの呼び出しができないクラスメソッドです。
こちらも、特異メソッド方式、特異クラス方式でサンプルを作ってみました。

特異メソッドを1つずつ定義する方法

特異メソッド方式の場合は、private_class_methodを使用して
privateにするメソッドを指定します。

以下のコードでは、showメソッドをprivateにしています。
外部から呼び出すとエラーになります。

class ItemInfo

    def self.show
        puts "show was called."
    end

    def self.show_item
        puts "show_item was called."
        show
    end

    private_class_method :show
end

begin
    ItemInfo.show
rescue => e
    puts "[#{e.class}] #{e.message}"
    # [NoMethodError] private method 'show' called for class ItemInfo
end

ItemInfo.show_item
# show_item was called.
# show was called.


特異クラスを開いてまとめて定義する方法

内容としては特異メソッド方式と同じです。
showメソッドをprivateにして外部から呼び出されるとエラーになります。

特異クラス方式の場合は、特異クラス定義の中で
公開範囲を指定しています。

以下のコードだとshow_itemメソッドはpublic、
showメソッドはprivateを指定しています。

class ItemInfo

    class << self
        public
        
        def show_item
            puts "show_item was called."
            show
        end

        private

        def show
            puts "show was called."
        end
    end
end

begin
    ItemInfo.show
rescue => e
    puts "[#{e.class}] #{e.message}"
    # [NoMethodError] private method 'show' called for class ItemInfo
end

ItemInfo.show_item
#show_item was called.
#show was called.



以上です。

【Ruby】例外の発生と例外処理

こんにちは。
本日はRubyメモです。

例外を意図的に発生させる

例外の発生はraiseを使用することで
意図的に例外を発生させることができます。

raise "エラー発生"
# エラー発生 (RuntimeError)

エラーの種類を指定しない場合は、RuntimeErrorとなります。

例外の種類を指定した場合は、
指定したエラーで例外を発せさせることができます。

raise ArgumentError, "引数不正"
# 引数不正 (ArgumentError)


例外をキャッチして処理を行う

例外をキャッチする場合は、以下のように記載します。

begin
    # 例外が発生する可能性がある処理
rescue => e
    # 例外が発生した時の処理
ensure
    # 例外の発生有無に関わらず実行する処理
end

raiseで意図的に例外を発生させて動きをみてみます。

begin
    # 意図的に例外を発生させる
    raise ArgumentError, "引数不正"

rescue => e
    puts "[#{e.class}] #{e.message}"

ensure
    puts "処理を終了します。"
end

#[ArgumentError] 引数不正
#処理を終了します。

rescueは、エラーの種類を指定することもできます。

begin
    raise ArgumentError, "引数不正"

rescue RuntimeError => e
    puts "[エラーA][#{e.class}] #{e.message}"

rescue ArgumentError => e
    puts "[エラーB][#{e.class}] #{e.message}"

ensure
    puts "処理を終了します。"
end

#[エラーB][ArgumentError] 引数不正
#処理を終了します。



以上です。

【Ruby】[超入門] 文字コードとBase64の変換

こんにちは。
本日はRubyメモです。

文字コードの判定

文字コードの判定を行うには
String#encodingを使用します。

euc = "こんにちは".encode("EUC-JP")
sjis = "こんにちは".encode("SJIS")
utf = "こんにちは".encode("UTF-8")

puts "euc => #{euc.encoding}"
puts "sjis => #{sjis.encoding}"
puts "utf => #{utf.encoding}"
# euc => EUC-JP
# sjis => Windows-31J
# utf => UTF-8


バイト配列で取得する

文字列をバイト配列で取得する場合は
String#bytesを使用します。

以下のサンプルは、16進数で表示しています。

utf = "こんにちは".encode("UTF-8")

puts "utf => #{utf.bytes.map { |b| format("%02x", b) }.join(" ") }"
# utf => e3 81 93 e3 82 93 e3 81 ab e3 81 a1 e3 81 af


Base64に変換

Base64の変換処理を行う場合は、標準ライブラリのbase64を使用します。

文字列からBase64に変換する場合はstrict_encode64を使用します。

require 'base64'

str = "こんにちは"
enc = Base64.strict_encode64(str)
puts "#{str} => #{enc}"
# こんにちは => 44GT44KT44Gr44Gh44Gv

Base64の文字列から元の文字列に戻す場合はdecode64を使用します。

require 'base64'
str = "こんにちは"
enc = Base64.strict_encode64(str)

message = Base64.decode64(enc)
puts "#{enc} => #{message}"
# 44GT44KT44Gr44Gh44Gv => こんにちは



以上です。