{"id":2827,"date":"2015-09-29T17:06:38","date_gmt":"2015-09-29T15:06:38","guid":{"rendered":"https:\/\/sgaul.de\/?p=2827"},"modified":"2015-11-30T21:40:31","modified_gmt":"2015-11-30T20:40:31","slug":"overriding-vs-overwriting","status":"publish","type":"post","link":"https:\/\/sgaul.de\/2015\/09\/29\/overriding-vs-overwriting\/","title":{"rendered":"Overwriting and Overriding with define_method"},"content":{"rendered":"
Recently we stumbled upon this inheritance issue,\u00a0which seemed very weird at\u00a0the first:<\/p>\n
class A\r\n def talk\r\n 'A'\r\n end\r\nend\r\n\r\nclass B < A\r\n def self.define_talk\r\n define_method :talk do\r\n super() << 'B'\r\n end\r\n end\r\nend\r\n\r\nclass C < B\r\n define_talk\r\n \r\n def talk\r\n super << 'C'\r\n end\r\nend\r\n\r\n> C.new.talk\r\n => \"AC\"<\/pre>\nThe talk addition from class B doesn’t appear, even though define_talk is triggered by Class C. C’s super call\u00a0seems to ignore its direct parent B.<\/p>\n
<\/p>\n
Overriding vs\u00a0Overwriting<\/h2>\n
The reason for that is the delayed execution of define_talk, which adds the talk method\u00a0to C rather than B. The previous definition of C is equivalent to this:<\/p>\n
class C < B\r\n # calling define_talk is equivalent to\r\n def talk\r\n super << 'B'\r\n end\r\n \r\n def talk\r\n super << 'C'\r\n end\r\nend<\/pre>\nThe second definition of talk\u00a0doesn’t override the first one, it overwrites<\/em> it<\/a>: The first definition is completely gone and therefore no longer available as super.<\/p>\n
Overriding with Anonymous Modules<\/h2>\n
To fix this we need to ensure that\u00a0B defines the method on B or another untouched inheritance layer. This layer can be an anonymous module created\u00a0and included by the define_talk method:<\/p>\n
class B < A\r\n def self.define_talk\r\n mod = Module.new do\r\n define_method :talk do\r\n super() << 'B'\r\n end\r\n end\r\n include mod\r\n end\r\nend<\/pre>\nNow C’s definition of talk only\u00a0overrides the one of the anonymous module, which is therefore still available as super.<\/p>\n
> C.new.talk\r\n => \"ABC\"<\/pre>\n","protected":false},"excerpt":{"rendered":"Recently we stumbled upon this inheritance issue,\u00a0which seemed very weird at\u00a0the first: class A def talk ‚A‘ end end class B < A def self.define_talk define_method :talk do super() << ‚B‘ end end end class C < B define_talk def talk super << ‚C‘ end end > C.new.talk => „AC“ The talk addition from class… Overwriting and Overriding with define_method<\/span> weiterlesen<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[91],"tags":[615,617,616,553,552],"_links":{"self":[{"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/posts\/2827"}],"collection":[{"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/comments?post=2827"}],"version-history":[{"count":5,"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/posts\/2827\/revisions"}],"predecessor-version":[{"id":2832,"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/posts\/2827\/revisions\/2832"}],"wp:attachment":[{"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/media?parent=2827"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/categories?post=2827"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sgaul.de\/wp-json\/wp\/v2\/tags?post=2827"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}