Inherit and override in the same time?

P

Philippe Lang

Hi Ruby gurus,

Let's say we have a Parent class, and a Child1 class that inherits from
the Parent class.

I'd like to create a Child2 class that inherits most of the Child1
class, except for one method, which I'd like to override completely. The
problem is that I need to call the method in the Parent class, and
apparently "super.super" is not supported:

----------------------------
class Parent
def go
puts 'parent'
end
end

class Child1 < Parent
def go
super
puts 'child1'
end
def a_method_id_like_to_inherit
end
end

class Child2 < Child1
def go
super.super
puts 'child2'
end
end

Child2.new.go=20
----------------------------
in `go': undefined method `super' for nil:NilClass (NoMethodError)
----------------------------

I ended up doing this, which apprently works.

----------------------------
class Parent
def go
puts 'parent'
end
end

class Child1 < Parent
def go
super
puts 'child1'
end
def a_method_id_like_to_inherit
end
end

class Child2 < Child1
def go
self.class.superclass.superclass.instance_method( :go ).bind( self
).call=20
puts 'child2'
end
end

Child2.new.go=20
----------------------------
parent
child2
----------------------------

Isn't there anything simpler than that? Or is that kind of pattern
considered as bad design maybe?

Philippe
 
J

James Coglan

[Note: parts of this message were removed to make it a legal post.]
I ended up doing this, which apprently works.

----------------------------
class Parent
def go
puts 'parent'
end
end

class Child1 < Parent
def go
super
puts 'child1'
end
def a_method_id_like_to_inherit
end
end

class Child2 < Child1
def go
self.class.superclass.superclass.instance_method( :go ).bind( self
).call
puts 'child2'
end
end

Child2.new.go


Smells a little of bad design. Consider putting the common methods for
Child1, Child2 into a module:

class Parent
end

class Child1 < Parent
include ChildStuff
end

class Child2 < Parent
include ChildStuff
end

Just a suggestion -- it's hard to really comment on a design without knowing
the problem you're trying to solve.
 
R

Rick DeNatale

[Note: parts of this message were removed to make it a legal post.]

Hi Ruby gurus,

Let's say we have a Parent class, and a Child1 class that inherits from
the Parent class.

I'd like to create a Child2 class that inherits most of the Child1
class, except for one method, which I'd like to override completely. The
problem is that I need to call the method in the Parent class, and
apparently "super.super" is not supported:

----------------------------
class Parent
def go
puts 'parent'
end
end

class Child1 < Parent
def go
super
puts 'child1'
end
def a_method_id_like_to_inherit
end
end

class Child2 < Child1
def go
super.super
puts 'child2'
end
end

Child2.new.go
----------------------------
in `go': undefined method `super' for nil:NilClass (NoMethodError)
----------------------------

I ended up doing this, which apprently works.

----------------------------
class Parent
def go
puts 'parent'
end
end

class Child1 < Parent
def go
super
puts 'child1'
end
def a_method_id_like_to_inherit
end
end

class Child2 < Child1
def go
self.class.superclass.superclass.instance_method( :go ).bind( self
).call
puts 'child2'
end
end

Child2.new.go
It's not clear WHY you want to do this but..

your self.class.superclass.superclass.instance_method:)go).bind(self).call

really doesn't do the same thing, in general as your desired super.super
(which I've not by the way seen in other dynamic OO languages either).

Consider what would happen if you added

class Child3 < Child2
end

Child3.new.go

I think that the right way to do this is to refactor the method to extract
just the behavior you want to control, so in this particular case something
like

class Parent
def go
puts 'parent'
end
end

class Child1 < Parent

def put_me
puts 'child1'
end

def go
super
put_me
end

end

class Child2 < Child1
def put_me
puts 'child2'
end
end

class Child3 < Child2
end

Parent.new.go
Child1.new.go
Child2.new.go
Child3.new.go

HTH
 
P

Philippe Lang

It's not clear WHY you want to do this but..

Hi Rick and James,

Thanks for your answer.

I tried to rewrite my example so it shows a little bit better WHY I'm
trying to do that.=20

------------------------------------

class Form
def initialize
puts "form preparation"
end
def search_data
puts "form search preparation"
yield
puts "form search cleanup"
end
end

class ProductForm < Form
def initialize
super
puts "product form widgets preparation"
end
def search_data
super do
puts "product search"
end
end
end

class ArchivedProductForm < ProductForm
def search_data
self.class.superclass.superclass.instance_method( :search_data
).bind( self ).call do
puts "archived product search"
end
end
end

ProductForm.new.search_data
puts "------------------"
ArchivedProductForm.new.search_data

------------------------------------
form preparation
product form widgets preparation
form search preparation
product search
form search cleanup
------------------
form preparation
product form widgets preparation
form search preparation
archived product search
form search cleanup
------------------------------------

Basically, a ProductForm or ArchivedProductForm are identical, except
the way they are being searched for. All the rest, like the widgets on
the form, are exactly the same.

I'm pretty sure now I have to refactor somehow my code, to keep things
clean. I guess the following code, with an extra class, is the way to
go:

------------------------------------

class Form
def initialize
puts "form preparation"
end
def search_data
puts "form search preparation"
yield
puts "form search cleanup"
end
end

class ProductBaseForm < Form
def initialize
super
puts "product form widgets preparation"
end
end

class ProductForm < ProductBaseForm
def search_data
super do
puts "product search"
end
end
end

class ArchivedProductForm < ProductBaseForm
def search_data
super do
puts "archived product search"
end
end
end

ProductForm.new.search_data
puts "------------------"
ArchivedProductForm.new.search_data

------------------------------------
form preparation
product form widgets preparation
form search preparation
product search
form search cleanup
------------------
form preparation
product form widgets preparation
form search preparation
archived product search
form search cleanup
 
P

Pit Capitain

2009/2/16 Philippe Lang said:
I tried to rewrite my example so it shows a little bit better WHY I'm
trying to do that.

Philippe, you could introduce a new method, for example #product_search:

class Form
def initialize
puts "form preparation"
end
def search_data
puts "form search preparation"
yield
puts "form search cleanup"
end
end

class ProductForm < Form
def initialize
super
puts "product form widgets preparation"
end
def search_data
super do
product_search
end
end
def product_search
puts "product search"
end
end

class ArchivedProductForm < ProductForm
def product_search
puts "archived product search"
end
end

(not tested)

Regards,
Pit
 
R

Robert Klemme

Hi Ruby gurus,

Let's say we have a Parent class, and a Child1 class that inherits from
the Parent class.

I'd like to create a Child2 class that inherits most of the Child1
class, except for one method, which I'd like to override completely. The
problem is that I need to call the method in the Parent class, and
apparently "super.super" is not supported:

----------------------------
class Parent
def go
puts 'parent'
end
end

class Child1 < Parent
def go
super
puts 'child1'
end
def a_method_id_like_to_inherit
end
end

class Child2 < Child1
def go
super.super
puts 'child2'
end
end

Child2.new.go
----------------------------
in `go': undefined method `super' for nil:NilClass (NoMethodError)
----------------------------

I ended up doing this, which apprently works.

----------------------------
class Parent
def go
puts 'parent'
end
end

class Child1 < Parent
def go
super
puts 'child1'
end
def a_method_id_like_to_inherit
end
end

class Child2 < Child1
def go
self.class.superclass.superclass.instance_method( :go ).bind( self
).call
puts 'child2'
end
end

Child2.new.go

IMHO the "bug" is in your inheritance design. You probably should rather do

class Parent
def go
puts 'parent'
end
end

class BaseChild < Parent
def a_method_id_like_to_inherit
puts 'Boo!'
end
end

class Child1 < BaseChild
def go
super
puts 'child1'
end
end

class Child2 < BaseChild
def go
super
puts 'child2'
end
end

Now, if there are no other classes that should derive from Parent you
might as well merge BaseChild and Parent.

Kind regards

robert
 
R

Rick DeNatale

[Note: parts of this message were removed to make it a legal post.]

Philippe, you could introduce a new method, for example #product_search:

class Form
def initialize
puts "form preparation"
end
def search_data
puts "form search preparation"
yield
puts "form search cleanup"
end
end

class ProductForm < Form
def initialize
super
puts "product form widgets preparation"
end
def search_data
super do
product_search
end
end
def product_search
puts "product search"
end
end

class ArchivedProductForm < ProductForm
def product_search
puts "archived product search"
end
end
Exactly!

This is what I recommended, recast into the "new" problem.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,153
Members
46,701
Latest member
XavierQ83

Latest Threads

Top