2013-08-03 8 views
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가 메소드를 찾는 방식으로 인해 이것이 작동하지 않을 것이라고 확신합니다.

내가 관심을 갖는 이유는 내가 작업하고있는 작업에서 이름 지정 규칙에 따라 여러 가지 정책을 적용 할 수 있었기 때문에 정책에 대한 참조를 얻을 수있는 좋은 방법이 있습니다. 다른 어떤 종류의 물체에 대해서. 나에게, syntatically,이 작업을 수행하는 것이 좋은 것 같다

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를 호출 할 수 어떤 의미가 있다고 생각하지 않습니다. 당신은 정책을 가지고 있습니다. 찾을 것이 아무것도 없습니다.

1) 사실, 거기에 선택적으로 루비에서 상속 할 수있는 클래스 방법을 정의하는 몇 가지 방법 :

그래서, 내 질문은 두 부분입니까?

2) 어디 선가 주어진 객체 에 대한 정책 이름을 추론하기위한 로직을 캡슐화 할 점을 감안하고,이 시점에서

나는 때문에, 그 대답이 '아니오'거의 확실 해요 그것은 내가 지금까지 시도한 것이 Policy 클래스가 틀림 없음을 증명하는 것처럼 보입니다. 장소, 대신이 종류의 것을 넣으시겠습니까?

감사합니다. 부분 모두에서 2. 매우 유용한 통찰력을 응답하는 1 부와 Linuxios 응답에 대한 JimLim에


업데이트

감사합니다.

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 메소드를 제공해야하는 이유가 있다면, 서브 클래스를 설정할 수는 있지만, 상속 된 서브 클래스를 호출하면 서브 클래스에 예외가 있다는 것을 알게된다.

둘 다 내 질문에 대답 한 "답"을 얻는 방법을 결정하는 것과 관련하여 "동점"의 경우 개인 습관은 평판이 낮은 사람의 답변을 수락하는 것이 었습니다. 시간.

도움 주셔서 감사합니다.

+0

아무것도하지 않고 예외를 발생시키는 서브 클래스에서'lookup' 메소드를 정의하는 것이 좋은 생각일까요? –

+0

undef_method가 적용될 수 있습니다. –

+0

@JimLim 그게 현실적인 대안으로 나를 때렸지 만, 다른 사람들이 하위 클래스를 만들 것이라는 생각이 들었습니다. 나는 오히려 한 가지 방법이 상속받을 때 단순히 존재하지 않는다는 관점에서 오히려 그 것이 었습니다. 아래 답변에 몇 가지 옵션이있는 것 같습니다. – Andrew

답변

2

undef_method 문서에 따르면,

명명 된 방법에 대한 호출에 응답에서 현재 클래스를 방지합니다. 이것을 remove_method와 비교해보십시오.이 메소드는 특정 클래스의 메소드 을 삭제합니다. 루비는 수퍼 클래스와 가능한 수신기를위한 혼합 모듈을 검색합니다.

class Policy 
    def self.lookup(object) 
    end 
end 

class RecordPolicy < Policy 
    class << self 
    undef_method :lookup 
    end 
end 

Policy.lookup nil 
# => nil 
RecordPolicy.lookup 
# => NoMethodError: undefined method `lookup' for RecordPolicy:Class 

#inherited 사용하여, 우리는 그 RecordPolicy의 인스턴스 메서드를 정의를 해제하기 때문에

class Policy 
    def self.lookup(object) 
    end 
    def self.inherited(sub) 
    sub.class_eval do 
     class << self 
     undef_method :lookup 
     end 
    end 
    end 
end 

class RecordPolicy < Policy 
end 

RecordPolicy.lookup 
# => NoMethodError: undefined method `lookup' for RecordPolicy:Class 

sub.class_eval { undef_method :lookup } 작동하지 않습니다 사용 할 수 있습니다. 대신 RecordPolicy의 eigenclass에서 호출해야합니다.

5

@ JimLim의 대답에 확장해야 할 것이 있습니다.

먼저이 값은 undef_methodremove_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는 언어 관습을 어지럽히고 혼란스럽고 직관적 인 클래스를 만들지 않고 행동을 서브 클래 싱하기 위해 이러한 것들을 명료하게 바꿀 수있는 큰 힘을줍니다.

+0

공유해 주셔서 감사 드리며, POLA에 대한 귀하의 의견에 진심으로 감사드립니다. 지금 나는 이것에 대해 궁금해하고있다. 나는 lookup 메소드를 구현 세부 사항으로 생각한다. 그것은 관련된 모듈의 다른 객체가 그것을 호출하기 때문에 public이지만, preference는 그 클래스를 상속하는 것을 제외하고는 클래스를 사용하지 않는 모듈 외부의 코드이다.클래스 메서드는 상속을 받지만 실제로 하위 클래스에서는 무시해야합니다. 클래스 메서드는 상속 받지만 상속 될 때 다르게 동작하거나 하위 클래스에 메서드가 제거 된 경우 제거됩니다. 필요 없어? – Andrew

+0

@andrew : 글쎄, 적어도 놀랍지 않은 것은 아마도 2라는 것입니다. 왜냐하면 라이브러리의 사용자/모든 문서를 읽는다면 무시해야한다는 것을 이해하기 때문에 문서에 있습니다. 예상되는 방식은 심지어 쓸모가 없다고하더라도, 그것이 가장 "놀라운"것이라고 생각합니다. – Linuxios