From: James Coglan Date: 2009-03-21T03:52:24+09:00 Subject: Re: self.inherited but wait until subclass is fully defined? --0016e6d999dacab35204659174a5 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit 2009/3/20 Ryan Davis > > On Mar 20, 2009, at 09:37 , Robert Klemme wrote: > > On 20.03.2009 17:22, matt neuburg wrote: >> >>> Howdy. I am a class. There are certain rules for what you are supposed >>> to do when you subclass me, so as a sanity check I wish to introspect >>> your subclass to make sure it's obeying the contract. >>> However, my problem is that self.inherited is called too early. >>> class C # this is me >>> def self.inherited(p) >>> #whatever >>> super >>> end >>> end >>> class B < C # this is you >>> # C's self.inherited is called right here >>> def yourFirstMethod >>> # etc. >>> end >>> end >>> So I can't, in my self.inherited, ask about what methods you have >>> defined, because you haven't defined them yet. This must have come up >>> before; is there an easy solution? Thx - m. >>> >> >> Even after the class definition methods can be added. You could catch >> that with method_added but if you require a minimum set of methods to be >> defined before class is used (e.g. instantiated) this will be difficult to >> track. One option would be to define method initialize in your class and do >> the check there. But this is still fragile because it might not be >> guaranteed that sub classes invoke it from their initialize... >> >> Another option would be to override the sub class's method "new" so you >> can do the check there. This might be a bit more robust but even "new" can >> be overridden by subclasses (although it isn't generally). >> >> I'd probably just omit the check. If any of your superclass methods >> invokes a method that is not defined you'll see this at runtime anyway. >> > > I agree with this in general for Matt's particular problem. The smalltalk > pattern of defining all contracted methods and having them raise > SubclassResponsibility is a good one to use in this situation. So, maybe a little helper: class Module def abstract_methods(*names) names.each do |name| define_method(name) { raise SubclassResponsibility } end end end For example class MyClass abstract_methods :foo, :bar end class Whizz < MyClass def foo; "foo!"; end end w = Whizz.new w.foo #=> "foo!" w.bar #=> error: SubclassResponsibility --0016e6d999dacab35204659174a5--