3

それで、私はいくつかのモデルで遊んでいて、サブクラスによるクラスメソッドの継承を本当に制限したい状況に遭遇しました。問題は、これまでのところ、これは実行できないという私の理解を確認した実験です。

私は単純に次のことを試しました:

class Policy
  class << self
    def lookup(object)
      #returns a subclass by analyzing the given object, following a naming convention
    end

    def inherited( sub )
      sub.class_eval { remove_method :lookup }
    end
  end
end

もちろん、サブクラスにはメソッドがないため、それは機能しません。それはスーパークラスにあります。その後、私は試しました:

def inherited( sub )
  class << Policy
    remove_method :lookup
  end
end

サブクラスが最初にロードされたときにスーパークラスからメソッドを取り除くことによって機能するという小さな詳細を除いて、それは魅力のように機能します。おっとっと!

したがって、Ruby がメソッドを検索する方法が原因で、これが機能しないことは確かです。

私が興味を持っている理由は、私が取り組んでいる動作では、命名規則に従って多くの異なるポリシーを持つことができ、他のクラスのポリシーへの参照を取得するためのきれいな方法が欲しいからです。オブジェクトの。私には、構文的に、これを行うのがいいようです:

class RecordPolicy < Policy
  # sets policy concerning records,
  # inherits common policy behavior from Policy
end

class Record
end

$> record = Record.new
=> #<Record:0x0000>
$> Policy.lookup(record)
=> RecordPolicy

ただし、 を呼び出せることに意味はないと思いますRecordPolicy#lookup。ポリシーを取得しました。その下には何もありません。

だから、私の質問は2つの部分です:

1) 実際、Ruby で継承できるクラス メソッドを選択的に定義する方法はありますか?

この時点で、それに対する答えは「いいえ」であると確信しています。したがって、

2)どこかで特定のオブジェクトのポリシー名を推測するためのロジックをカプセル化したい場合、これまでに試したことは、ポリシークラスが間違った場所であることを示しているように見えます。どこに置きますか代わりにこういうこと?

ありがとう!


アップデート

パート 1 に回答してくれた JimLim と、パート 2 に回答してくれた Linuxios に感謝します。両方からの非常に有益な洞察。

FWIW、Linuxiosの発言を熟考した後、私がやろうと決めたのは次のとおりです。

class << self
  def lookup( record )
    if self.superclass == Policy
      raise "No default naming convention exists for subclasses of Policy. Override self.lookup if you want to use it in a subclass."
    else
      # naming convention lookup goes here
    end
  end
end

これは、このコードがどのように使用されるかについて最も驚くべきことではないように感じます。サブクラスに #lookup メソッドを提供する何らかの理由がある場合は、それを設定できますが、継承されたものを呼び出すと、そうする意味がないことを伝える例外が発生します。

どちらも私の質問の半分に答えたので、誰が「答え」を得るかをどのように決定するかについては、「引き分け」の場合、私の個人的な習慣は、その時点で評判の低い人からの答えを受け入れることです.

助けてくれてありがとう!

4

2 に答える 2

5

@JimLimの答えを拡張するだけです。

undef_methodまず、これは whatとの違いにより機能しremove_methodます。

remove_method実際にはメソッドを完全に削除します。undef_method、ドキュメントによると:

現在のクラスが名前付きメソッドの呼び出しに応答しないようにします。

(強調鉱山)。

しかし...

あなたの問題が質問で示したものである場合、あなたはこれについて間違っていると思います。電話できるのに何が悪いのRecordPolicy.lookup?役に立たないかもしれませんが、最小の驚きの原則に従います。クラスはこのPolicyメソッドに適した場所ですが、実装すると次のようになります。

def self.lookup(obj)
  if(self.superclass == Policy) #It's a subclass, return self
    return self
  else
    #look stuff up
  end
end

場違いなことは何もありません。メソッドがオブジェクトに対して役に立たないという理由だけで、*言語*的に意味がある場合は、いじってはいけません。Ruby は、言語の慣習を壊したり、混乱した直感的でないクラスやサブクラス化の動作を作成したりしないように、これらのことを明確にするために変更する強力な力を提供します。

于 2013-08-03T04:43:54.477 に答える