Ruby: クラスの型をチェックするグローバルメソッドを作成する (Pair)

概要

変数がペア型 (独自のカスタマイズされたクラス) であるかどうかを確認するグローバル ブール メソッドを作成しようとしています。ただし、実行しようとするとエラーが発生します

Project4.rb:83:in `<main>': private method `pair?' called for #<Pair:0x00000212de6861e8 @value1=5, @value2=7> (NoMethodError)

puts a.pair?
      ^^^^^^ 

私は何をしますか?私のコードは以下です。

#Pair (class): Takes two values and creates a list from them. Executing the code should return a list without displaying any output.
#   Returns: A list of at least two elements.
#   Parameters:
#       value1 (any class, including pair) - a value to insert into list.
#       value2 (any class, including pair) - another value to insert into list.
#
#Declare class `Pair`
class Pair
    #Initialize
    def initialize(value1, value2)
        @value1 = value1
        @value2 = value2
    end

    #Method: car - return the car of the pair.
    def car
        return @value1
    end
    
    #Method: cdr - return the cdr of the pair.
    def cdr
        return @value2
    end
    
    #Method: to_s - Return string representation of the pair.
    # def to_s
    #     "(#{@value1} . #{@value2})" 
    # end

    #Method: list? - returns true if pair is a valid list and false otherwise.
    def list?
        #If value2 is a pair...
        if (@value2.class == Pair)
            #...Recursively call the list? method again with the cdr.
            cdr.list? #Recursion
        else
            #If value2 is a null (nil) value, then it is a list.
            if (@value2 == nil)
                return true
            else
                return false
            end
        end
    end

    #Method: count - If the pair is a list, return the number of items in the top level of the list. Return false otherwise.

    #Method: append(other) - If the pair is a list, append should return a new list consisting of `other`` appended to the original list. 

    #Method: null? -  returns true only if the pair is an empty list.
    def null?

    end

    #Implement a null/empty list value.
    def self.null
        nil
    end

end

#Implement a global `pair?` method. MUST NOT TAKE PARAMETERS!
def pair?
    if (is_a? Pair)
        return true
    else
        return false
    end
end

できるだけ早くご返信ください。

解決策

グローバル メソッドはレシーバーを必要とせず、関数形式 (たとえば、put やループ) で呼び出すことができます。ただし、このメソッドは is_a? に基づいているため、レシーバーが必要です。

メソッドを動作するグローバル メソッドに変えるには、オブジェクトを渡す必要があります。

def pair?(obj)
  obj.is_a?(Pair)
end

さて、気づきました。おそらく、最初からグローバル メソッドではなく、Object のインスタンス メソッドが必要です。

class Object
  def pair?
    is_a?(Pair)
  end
end

これは、任意のオブジェクトに対して呼び出すことができるという意味で「グローバル」です。

継承を利用することで、明示的な型チェックを省略することもできます。 Object#pair を実装しますか?すべてのオブジェクトに対してデフォルト値 false を提供するメソッド:

class Object
  def pair?
    false
  end
end

そして、Pair クラスでそれをオーバーライドして true を返します。

class Pair
  def pair?
    true
  end
end

例:

Object.new.pair? #=> false
"a string".pair? #=> false

Pair.new.pair?   #=> true

これはまさにゼロですか?動作します。Object#nil の実装を参照してください。と NilClass#nil?。

Object にメソッドを追加すると、それらのメソッドがすべてのオブジェクトで使用可能になるため、クラスが乱雑になる可能性があることに注意してください。 OOP の原則を調べるのには最適ですが、一般的には行うべきではありません。