goby icon indicating copy to clipboard operation
goby copied to clipboard

`super` and method overwrite mechanism design

Open st0012 opened this issue 7 years ago • 6 comments
trafficstars

  • We should support method overwritten and monkey-patching
  • All methods (public or private) can do this
  • We shouldn't support Ruby's super keyword. But we can
    • Support something like super_from(GrandClass) to let users explicitly specify which ancestor's method they super to
    • Not supporting super-like mechanism at all

st0012 avatar Feb 13 '18 16:02 st0012

We shouldn't support Ruby's super keyword. But we can

Can you elaborate a bit on this one? Without super(), how do inherited methods invoke the ancestor, in particular, initialize()? For the initialize() case, there is really no need for, say, super_from(), as invocation will go up the hierarchy.

Also, I'm a bit confused about the relationship between super and monkeypatching, as they apply to different areas (if I've understood well).

64kramsystem avatar Feb 13 '18 21:02 64kramsystem

Is the monkey-patching moderate like Ruby's refinement?

hachi8833 avatar Feb 14 '18 00:02 hachi8833

@saveriomiroddi @hachi8833 Change the title to be method overwriting, does that look better?

Can you elaborate a bit on this one? Without super(), how do inherited methods invoke the ancestor, in particular, initialize()? For the initialize() case, there is really no need for, say, super_from(), as invocation will go up the hierarchy.

class GrandClass
  def initialize(foo)
    @foo = foo
  end
end

class ParentClass < GrandClass; end

module Bar
  def initialize(foo)
    @foo = foo + 10
  end
  # some other methods
end

class ChildClass < ParentClass
  include Bar
  def initialize(foo)
     super_from(GrandClass, foo) # This will skip the Bar's initialize
  end
end

I think this gives users a more clear view and control about the method inheritance.

st0012 avatar Feb 14 '18 02:02 st0012

So, the term exact is method overriding.

I don't think specific support for module overriding initialize() should be added.

The reason is that modules are used for composition; such override would interfere with inheritance.

Interestingly, this behavior could be considered multiple inheritance, which is not a very "appreciated" design (I've personally never seen it).

This is a silly example of why modules should not override a class initializer:

class Car
  def initialize
    start_engine
  end
end

module TopOpeningDoors
  def initialize
    open_doors
  end
end

class Ferrari < Car
  include TopOpeningDoors

  def initialize
    super_from(TopOpeningDoors) # won't start_engine

    start_turbines
  end
end

64kramsystem avatar Feb 15 '18 21:02 64kramsystem

@saveriomiroddi I used initialize is because you mentioned it earlier. I think initialization override can be another topic actually. Let me give you a different example:

class User
  def to_xml
   serialize(:email, :name)
  end
end

class Member < User
  def to_xml
   serialize(:email, :name, :member_id)
  end
end

class NullMember < Member
  def to_xml
    super_from(User)
  end
end

NullMember.new.to_xml #=> will only have email and name field

st0012 avatar Feb 16 '18 01:02 st0012

Ah! I see. Adding doesn't hurt :smile: :+1:

I think modules overriding should be taken into account as well (eg. the case where Member#to_xml is defined in another module, and not in Member), but maybe I'm stating the obvious :smile:.

64kramsystem avatar Feb 16 '18 10:02 64kramsystem