2016-12-07 5 views
2

class_evalinstance_evalは、メソッドの定義のような場合にはかなり予測可能です。私はまた、クラスのインスタンスとクラスのシングルトン(別名固有クラス)の違いを理解しています。Rubyの深いクラスclass_evalとinstance_eval

しかし

私は次のような唯一の事を把握することはできません。 一部strageの目的のために、私たちはシングルトンであることを、既存のクラスを作りたい、のは言ってみましょう。どちらの場合も

class A; end 
class B; end 

A.class_eval do 
    private :new 
end 

B.instance_eval do 
    private :new 
end 

NameError: undefined method 'new' for class 
Did you mean? new 

を持ってはい、私はまさにこの方法を意味します。

はまた、これらの二つの変異体は、いずれの場合も、クラスオブジェクトでselfポイント

A.class_eval do 
    class << self 
    private :new 
    end 
end 

A.new 
=> NoMethodError: private method 'new' called for A:Class 

B.instance_eval do 
    class << self 
    private :new 
    end 
end 

B.new 
=> NoMethodError: private method 'new' called for B:Class 

どのように来るように、同じ結果を与えますか?誰もがこれについて光を当てることができますか?

+0

Rubyのクラスの 'new'は実際に' initialize'を使って定義されています。 ':new'を':initialize'に置き換えてみてください。 – casraf

+0

@casrafこれは間違いです。 'new'はClass(すべてのクラスのスーパークラス)によって定義され、2つのことを行います([the docs](https://ruby-doc.org/core-2.3.1/Class.html#method-c-new )): "' allocate'を呼び出して* class *クラスの新しいオブジェクトを作成し、そのオブジェクトの 'initialize'メソッドを呼び出して* args *を渡します。これは、オブジェクトが構築されるたびに呼び出されるメソッドです.newを使用します。あるクラスで 'initialize'を定義(オーバーライド)すると、' new'を定義したり変更したりすることができません。他のクラスのメソッドと同じように 'new'をオーバーライドすることができます。 –

+0

私の悪いです。明確化のおかげで:) – casraf

答えて

0

ここにあるものを自己のぞいてみましょう:私たちは、次の出力を得る

class A 
    puts self.inspect 

    class << self 
    puts self.inspect 
    end 
end 

A.class_eval { 
    puts self.inspect 

    class << self 
    puts self.inspect 
    end 
} 

A.instance_eval{ 
    puts self.inspect 

    class << self 
    puts self.inspect 
    end 
} 

A 
#<Class:A> 
A 
#<Class:A> 
A 
#<Class:A> 

class_evalメソッドメソッドは、モジュール(したがって、クラス)のために定義されており、内部に評価モジュール(クラス)のコンテキスト。 instance_evalメソッドは、BasicObjectのコンテキスト内で評価されます。これらのケースでは、2つ(実際には3つ)は同じものです。

しかし、メソッドがの場合、評価ブロック内にが作成され、class_evalがインスタンスメソッドを作成し、instance_evalがクラスメソッドを作成するという事実を知っています。その観察のための優れた投稿が既にあります:

関連する問題