Forum: Ruby Super super ?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Eaf2890855aa289fc41a72d1ad0e330e?d=identicon&s=25 Marc-antoine Kruzik (kingkadelfek)
on 2009-05-19 21:29
Hello, I'm looking for informations about "super".

I have 3 classes : grandfather, father, and son.
And they all have a method named "say_hello".



[code]
class Grand_father
  def say_hello
    puts "Grand Father : Hello"
  end
end

class Father < Grand_father
  def say_hello
    super
    puts "Father : Hello"
  end
end

class Son < Father
  def say_hello
    super
    puts "Son : Hello"
  end
end
[/code]

s = Son.new
s.say_hello
Grand Father : Hello
Father : Hello
Son : Hello

But now, I would that Son didn't call Father, but directly Grand_father.

s.say_hello
Grand Father : Hello
Son : Hello

How could I do that ?
391f9b787cdc12aa2c179713f5103e3a?d=identicon&s=25 Ilan Berci (iberci)
on 2009-05-19 22:36
Marc-antoine Kruzik wrote:

>
> But now, I would that Son didn't call Father, but directly Grand_father.
>
> s.say_hello
> Grand Father : Hello
> Son : Hello
>
> How could I do that ?

I am taking a break at work so I can't test it, but could you please
try:
super.super.say_hello
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2009-05-19 22:45
(Received via mailing list)
On 19.05.2009 21:29, Marc-antoine Kruzik wrote:
>     puts "Grand Father : Hello"
> class Son < Father
> Father : Hello
> Son : Hello
>
> But now, I would that Son didn't call Father, but directly Grand_father.
>
> s.say_hello
> Grand Father : Hello
> Son : Hello
>
> How could I do that ?

You can do

class Son < Father
   def say_hello
     Grand_father.instance_method(:say_hello).bind(self).call
     puts "Son : Hello"
   end
end

However, as the weird construction indicates something might be wrong
with this kind of design.  If you assume that the method actually had
side effects on the instance's state and you leave out one class in the
chain you likely end up with an instance in an inconsistent state.  In
that case the design probably needs some work.

Btw, if Father does not define say_hello super will automatically call
Grand_father's method.

Kind regards

  robert
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2009-05-19 23:20
(Received via mailing list)
On 19.05.2009 22:36, Ilan Berci wrote:
> I am taking a break at work so I can't test it, but could you please
> try:
> super.super.say_hello

This won't work - at least not in the way you intended. :-)

Kind regards

  robert
B57c5af36f5c1f33243dd8b2dd9043b1?d=identicon&s=25 F. Senault (Guest)
on 2009-05-20 10:00
(Received via mailing list)
Le 19 mai à 21:29, Marc-antoine Kruzik a écrit :

> Hello, I'm looking for informations about "super".
/.../
> I have 3 classes : grandfather, father, and son.
> And they all have a method named "say_hello".
> But now, I would that Son didn't call Father, but directly Grand_father.
>
> s.say_hello
> Grand Father : Hello
> Son : Hello
>
> How could I do that ?

As others said, refactor, there's a problem with you inheritance logic.

That being said, you could work in the Father class like this to obtain
the wanted result :


class Father < Grand_father
  def say_hello
    super
    puts "Father : Hello" unless self.is_a? Son
  end
end

Fred
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2009-05-20 10:52
(Received via mailing list)
2009/5/20 F. Senault <fred@lacave.net>:

> That being said, you could work in the Father class like this to obtain
> the wanted result :
>
>
> class Father < Grand_father
>  def say_hello
>    super
>    puts "Father : Hello" unless self.is_a? Son
>  end
> end

Frankly, I find that even worse than my hack.  The reason: now Father
needs to know something about a sub class so we have a circular
dependency.  That's usually a bad thing to have.  Consider, all these
classes are in different files and someone only needs Father and
Grand_father: code will break in Father because Son is undefined.
It's ok if Son knows something about his parents but not otherwise.

Kind regards

robert
A20f57356110f62f93f7555a4bbb96af?d=identicon&s=25 KDr2 (Guest)
on 2009-05-20 11:23
(Received via mailing list)
class Object
  def super!(n,*args)
    method=caller[0][%r/.*?`(.*?)'/,1].to_sym
    klass=self.class.ancestors[n]
    klass.instance_method(method).bind(self).call(*args)
  end
end


class Grand_father
 def say_hello
   puts "Grand Father : Hello"
 end
end

class Father < Grand_father
 def say_hello
   super
   puts "Father : Hello"
 end
end

class Son < Father
 def say_hello
   super! 2
   puts "Son : Hello"
 end
end

s = Son.new
s.say_hello


On Wed, May 20, 2009 at 3:29 AM, Marc-antoine Kruzik
B57c5af36f5c1f33243dd8b2dd9043b1?d=identicon&s=25 F. Senault (Guest)
on 2009-05-20 11:25
(Received via mailing list)
Le 20 mai à 10:51, Robert Klemme a écrit :

> Frankly, I find that even worse than my hack.

Of course...  :)

Fred
Eaf2890855aa289fc41a72d1ad0e330e?d=identicon&s=25 Marc-antoine Kruzik (kingkadelfek)
on 2009-05-20 15:39
Ilan Berci wrote:
> I am taking a break at work so I can't test it, but could you please
> try:
> super.super.say_hello

Too bad it doesn't work. But it was pretty logical. :)


@ KDr2

That is exactly what I needed ! :D
Thank you very much.
59528506e6297141161afcde91d677c9?d=identicon&s=25 Nicolai Reuschling (codeblogger)
on 2009-05-20 16:43
(Received via mailing list)
2009/5/20 Marc-antoine Kruzik <kadelfek@kadelfek.com>

>
> Too bad it doesn't work. But it was pretty logical. :)
>
>
I don't think it was logical, but I guess, that's a matter of taste and
expectation of what 'super' does.
And still: KDr2's solution is bad software design.

Regards
Nicolai
391f9b787cdc12aa2c179713f5103e3a?d=identicon&s=25 Ilan Berci (iberci)
on 2009-05-20 16:46
Robert Klemme wrote:

>
> class Son < Father
>    def say_hello
>      Grand_father.instance_method(:say_hello).bind(self).call
>      puts "Son : Hello"
>    end
> end
>
>

Ahh.. cool! Thanks for the bind() solution, I am aware of it but it
always falls to the back of my head.. I blame either my age, marriage,
or kids on this one..

ilan
Eb658fffacf97d23cf7df98003d38017?d=identicon&s=25 Pieter V. (Guest)
on 2009-05-20 17:04
(Received via mailing list)
Depending on your purpose, it may make sense to allow the caller to
specify which class to invoke the method in.  (This won't frequently
be the case, but since you're specifically looking to invoke your
Grandfather's method, it might apply here.)

--------8<-------------------------

def Grandfather
  def say_hello(klass=self.class)
    return super unless self.is_a?(klass)
    puts 'Grandfather: Hello'
  end
end

def Father < Grandfather
  def say_hello(klass=self.class)
    return super unless self.is_a?(klass)
    puts 'Father: Hello'
  end
end

def Son < Father
  def say_hello(klass=self.class)
    return super(Grandfather) unless self.is_a?(klass)
    puts 'Son: Hello'
  end
end

--------8<-------------------------

It's not a best practice, but it might prove useful enough for your
case.
Eaf2890855aa289fc41a72d1ad0e330e?d=identicon&s=25 Marc-antoine Kruzik (kingkadelfek)
on 2009-05-20 17:19
Pieter V. wrote:
> Depending on your purpose, it may make sense to allow the caller to
> specify which class to invoke the method in.  (This won't frequently
> be the case, but since you're specifically looking to invoke your
> Grandfather's method, it might apply here.)
>
> It's not a best practice, but it might prove useful enough for your
> case.

This was just an example. These methods have sometimes arguments, so I
had to find something else.

Because we found by ourselves two solutions, and yours was one of these.
The other was to use aliases, but it was bad.
This topic is locked and can not be replied to.