Created
October 29, 2012 11:33
-
-
Save unixcharles/3973073 to your computer and use it in GitHub Desktop.
DelegateClass and "superclass mismatch for class" errors
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'delegate' | |
class Klass < DelegateClass(String) | |
# ... | |
end | |
class Klass < DelegateClass(String) | |
# Re-open the class | |
end | |
# => TypeError: superclass mismatch for class Klass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'delegate' | |
DELEGATE_STRING = DelegateClass(String) unless defined?(DELEGATE_STRING) | |
class Klass < DELEGATE_STRING | |
# ... | |
end | |
class Klass < DELEGATE_STRING | |
# Re-open the class | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
> require 'delegate' | |
=> true | |
> DelegateClass(String).object_id == DelegateClass(String).object_id | |
=> false |
Just to note why this happens, DelegateClass(SomeClass)
is really doing Class.new(SomeClass)
and assigning it as the superclass. That's why it's a different object and not the same superclass each time.
Thanks for the explanation of the issue -- had me scratching my head. I was running into this when reloading source files from a pry session to pick up changes. Chose to do something similar in a module, to eliminate the ...unless defined? boilerplate per class. It may well be bad ruby - I'm a dabbler.
# This module wraps DelegateClass to eliminate the error on reload, which is an aggravation during development
#
# To use it, just replace any incidence of
#
# class MyClass < DelegateClass(SomeOtherClass)
#
# with
#
# class MyClass < NMD::ExplicitDelegator.to(SomeOtherClass)
module NMD
module ExplicitDelegator
class << self
attr_accessor :class_cache
def to superclass
superclass_id = superclass.to_s
@class_cache = {} if @class_cache.nil?
@class_cache[superclass_id] = DelegateClass(superclass) if @class_cache[superclass_id].nil?
@class_cache[superclass_id]
end
end
end
end
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for posting this. Ran into this issue today.