Inheritance related problem

Note: this is *not* a ruby bug. its a general query.
Perhaps best explained with sample code.

#!/usr/bin/env ruby -w

class Parent
  def printa arg
      puts "inside parent printa #{arg} "
      printb arg
  end
  def printb arg
      puts "inside parent printb #{arg} "
      puts "--> #{arg} "
  end
end

class Child < Parent
  def printa arg
      puts "inside child printa #{arg} reduced 1 "
      # 1 is actually some other instance level variable
      super arg-1
  end
  def printb arg
      puts "inside child printb #{arg} reduced 1"
      super arg-1
  end
end

if __FILE__ == $0
  begin
      p = Parent.new
      c = Child.new
      puts " parent calls with 5 and 6"
      p.printa 5
      #p.printb 6
      puts " === child calls with 7 === "
      c.printa 7
      #c.printb 7
  ensure
  end
end

Class Child extends Parent. It extends 2 methods by modifying the
incoming parameter and then calling super. One of these methods printa
calls printb.

When Parent's printa is called, it calls it own printb.
However, when Child's printa is called, it calls Parent's printa, which
(in this case) i was hoping would call Parent's printb directly. But it
(correctly) calls Child's printa which once again reduces the arg.

So my arg gets reduced twice. I suppose i could use some flags to
prevent this, But is there any direct way i can coerce Parent printa to
call only Parent printb.

When you execute the above code, you will see that 7 gets decremented 2
times.

Attachments:
http://www.ruby-forum.com/attachment/4448/test.rb

···

--
Posted via http://www.ruby-forum.com/.

Hi,

I'm going to give you a meta-answer to the problem...

If the two printb routines do the same thing, then child printb is redundant. Remove it.

If they do different things, then they should have different names - problem avoided.

I don't know enough ruby to answer your specific problem.

Regards

Ian

R. Kumar wrote:

···

Note: this is *not* a ruby bug. its a general query.
Perhaps best explained with sample code.

#!/usr/bin/env ruby -w

class Parent
  def printa arg
      puts "inside parent printa #{arg} "
      printb arg
  end
  def printb arg
      puts "inside parent printb #{arg} "
      puts "--> #{arg} "
  end
end

class Child < Parent
  def printa arg
      puts "inside child printa #{arg} reduced 1 "
      # 1 is actually some other instance level variable
      super arg-1
  end
  def printb arg
      puts "inside child printb #{arg} reduced 1"
      super arg-1
  end
end

if __FILE__ == $0
  begin
      p = Parent.new
      c = Child.new
      puts " parent calls with 5 and 6"
      p.printa 5
      #p.printb 6
      puts " === child calls with 7 === "
      c.printa 7
      #c.printb 7
  ensure
  end
end

Class Child extends Parent. It extends 2 methods by modifying the
incoming parameter and then calling super. One of these methods printa
calls printb.

When Parent's printa is called, it calls it own printb.
However, when Child's printa is called, it calls Parent's printa, which
(in this case) i was hoping would call Parent's printb directly. But it
(correctly) calls Child's printa which once again reduces the arg.

So my arg gets reduced twice. I suppose i could use some flags to
prevent this, But is there any direct way i can coerce Parent printa to
call only Parent printb.

When you execute the above code, you will see that 7 gets decremented 2
times.

Attachments:
http://www.ruby-forum.com/attachment/4448/test.rb

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

No virus found in this incoming message.
Checked by AVG - www.avg.com Version: 9.0.733 / Virus Database: 271.1.1/2657 - Release Date: 01/30/10 07:35:00

When Parent's printa is called, it calls its own printb.
However, when Child's printa is called, it calls Parent's printa, which
(in this case) i was hoping would call Parent's printb directly. But it
(correctly) calls Child's printa which once again reduces the arg.

So my arg gets reduced twice. I suppose i could use some flags to
prevent this, But is there any direct way i can coerce Parent printa to
call only Parent printb.

I'm having trouble understanding how you got into this position. I'm
assuming that you don't own Parent, and so have to work your magic in
Child. For the specific example you described, the following will
work...

Change Child#printa to:
def printa arg

  # The following block gets evaluated with Child as self
  child_print_b = Child.class_eval do

    # Save the Child method
    print_b = instance_method(:printb)

    # Remove it from the class
    remove_method :printb

    # Return it to the function for later restoration
    print_b
  end

  puts "inside child printa #{arg} reduced 1 "
  # 1 is actually some other instance level variable

  # This call will now eventually call Parent.printb
  # because there is no Child.printb
  super arg-1

  # Restore the original printb
  Child.class_eval do
    define_method :printb, child_print_b
  end
end

Outputs:
parent calls with 5
inside parent printa 5
inside parent printb 5
--> 5
=== child calls with 7 ===
inside child printa 7 reduced 1
inside parent printa 6
inside parent printb 6 <-------- Parent::printa called from
Child::printa calls Parent::printb
--> 6
inside child printb 7 reduced 1
inside parent printb 6
--> 6

I don't know if that's what the original post meant, but I'm
interested in knowing how to specify the exact class which method is
called when inheritance is involved.

Example (C++):
class Father
{
  virtual void m();
}

class Child
{
   void m();
   void aM() {Father::m();}
}

This forces the call to the method "m" of the Father class, rather
than using Child's. Is this possible in Ruby; if yes, how ? If
no...why ? :frowning:

TIA,

···

2010/1/31 R. Kumar <sentinel.2001@gmx.com>:

[...]
So my arg gets reduced twice. I suppose i could use some flags to
prevent this, But is there any direct way i can coerce Parent printa to
call only Parent printb.

--
Xavier NOELLE

Ian Hobson wrote:

Hi,

I'm going to give you a meta-answer to the problem...

If the two printb routines do the same thing, then child printb is
redundant. Remove it.

If they do different things, then they should have different names -
problem avoided.

I don't know enough ruby to answer your specific problem.

Regards

Ian

They need to have the same name since Child extends the functionality of
Parent. Both classes will be used in the same situation. That's why
Child extends Parent.

···

--
Posted via http://www.ruby-forum.com/\.

Sean DeNigris wrote:

When Parent's printa is called, it calls its own printb.
However, when Child's printa is called, it calls Parent's printa, which
(in this case) i was hoping would call Parent's printb directly. But it
(correctly) calls Child's printa which once again reduces the arg.

So my arg gets reduced twice. I suppose i could use some flags to
prevent this, But is there any direct way i can coerce Parent printa to
call only Parent printb.

I'm having trouble understanding how you got into this position. I'm
assuming that you don't own Parent, and so have to work your magic in
Child. For the specific example you described, the following will
work...

I own both. Parent is a wrapper around ncurses Window. Child is a
wrapper around ncurses Pad. However, they are used in a similar manner.
So in the original app, i used only Window. Now in many cases I use Pad.
They both should work interchangeably since they essentially do the same
thing but often in different ways. An object could use Window, or Pad.

However, stuff like printing a border or writing a string onto the
window are essentially the same except that the offsets in Window are
absolute whereas the Pad offsets are relative. So when Pad calls super
it only has to make the relative offsets absolute:

    def printstring(row, col, value, color, attrib=Ncurses::A_NORMAL)
      super(row - @top, col - @left, value, color, attrib)
    end # printstring

    def print_border row, col, height, width, color,
att=Ncurses::A_NORMAL
      super(row - @top, col - @left, height, width, color, att)
    end

Now in the parent Window, print_border does a call to printstring to
reset the background. Unfortunately, the child's printstring gets called
and @top and @left get decremented again.

I looked at your workaround -- a bit complicated, and could slow things
down since display has to be fast. I can use a variable that I set and
check, however, is there some direct way in ruby. I know the answer is
most likely NO, but just thought i'd ask in case i've overlooked
something.

···

--
Posted via http://www.ruby-forum.com/\.

Example (C++):
class Father
{
  virtual void m();
}

class Child
{
   void m();
   void aM() {Father::m();}
}

This forces the call to the method "m" of the Father class, rather
than using Child's. Is this possible in Ruby; if yes, how ? If
no...why ? :frowning:

TIA,

If you are saying that aM() forces a call to the parent's m() and of
course you have inherited from Father, then yes.

def aM
  super.m
end

···

--
Posted via http://www.ruby-forum.com/\.

So why not just factor out what's different between Parent and Child

class Parent
  def printstring(row, col, ... other parameters omitted)
      row, col = *transform(row, col)
      # do whatever you need
  end

  def transform(row, col)
     [row, col]
  end
end

class Child < Parent
   def transform(row, col)
       [row - @top, col - @left]
   end
end

···

On Mon, Feb 1, 2010 at 1:54 AM, R. Kumar <sentinel.2001@gmx.com> wrote:

Sean DeNigris wrote:

When Parent's printa is called, it calls its own printb.
However, when Child's printa is called, it calls Parent's printa, which
(in this case) i was hoping would call Parent's printb directly. But it
(correctly) calls Child's printa which once again reduces the arg.

So my arg gets reduced twice. I suppose i could use some flags to
prevent this, But is there any direct way i can coerce Parent printa to
call only Parent printb.

I'm having trouble understanding how you got into this position. I'm
assuming that you don't own Parent, and so have to work your magic in
Child. For the specific example you described, the following will
work...

I own both. Parent is a wrapper around ncurses Window. Child is a
wrapper around ncurses Pad. However, they are used in a similar manner.
So in the original app, i used only Window. Now in many cases I use Pad.
They both should work interchangeably since they essentially do the same
thing but often in different ways. An object could use Window, or Pad.

However, stuff like printing a border or writing a string onto the
window are essentially the same except that the offsets in Window are
absolute whereas the Pad offsets are relative. So when Pad calls super
it only has to make the relative offsets absolute:

def printstring(row, col, value, color, attrib=Ncurses::A_NORMAL)
super(row - @top, col - @left, value, color, attrib)
end # printstring

def print_border row, col, height, width, color,
att=Ncurses::A_NORMAL
super(row - @top, col - @left, height, width, color, att)
end

Now in the parent Window, print_border does a call to printstring to
reset the background. Unfortunately, the child's printstring gets called
and @top and @left get decremented again.

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

If you are saying that aM() forces a call to the parent's m() and of
course you have inherited from Father, then yes.

Yes, my mistake, I forgot the "public Father".

def aM
super.m
end

Yes, indeed, but what if I need to call a specific parent's method ?
Say Parent > Child > Grandchild. Is it possible to Parent::m in
Grandchild (other than super.super.m(), if it works :-)) ?

···

2010/2/5 R. Kumar <sentinel.2001@gmx.com>:

--
Xavier NOELLE

def aM
super.m
end

Am I missing something? "super" calls the method with the same name
in the superclass. So here, it calls Child#aM (which doesn't exist in
this example), then m would be called on whatever that call returned

class Parent
  def a
    puts "parent a"
  end
end

class Child < Parent
  def a
    puts "child a"
  end
end

class Grandchild < Child
  def a
    puts "grandchild a"
  end

  def grandpa_a
    super.a
  end
end

g = Grandchild.new.grandpa_a

Output:
test.rb:19:in `grandpa_a': super: no superclass method
`grandpa_a' (NoMethodError)

I can't think of a way to do what you want except by the methods
suggested previously.

Sean

Just to be clear I meant to say why not just factor out JUST what's different.

···

On Mon, Feb 1, 2010 at 8:59 AM, Rick DeNatale <rick.denatale@gmail.com> wrote:

On Mon, Feb 1, 2010 at 1:54 AM, R. Kumar <sentinel.2001@gmx.com> wrote:

Sean DeNigris wrote:

When Parent's printa is called, it calls its own printb.
However, when Child's printa is called, it calls Parent's printa, which
(in this case) i was hoping would call Parent's printb directly. But it
(correctly) calls Child's printa which once again reduces the arg.

So my arg gets reduced twice. I suppose i could use some flags to
prevent this, But is there any direct way i can coerce Parent printa to
call only Parent printb.

I'm having trouble understanding how you got into this position. I'm
assuming that you don't own Parent, and so have to work your magic in
Child. For the specific example you described, the following will
work...

I own both. Parent is a wrapper around ncurses Window. Child is a
wrapper around ncurses Pad. However, they are used in a similar manner.
So in the original app, i used only Window. Now in many cases I use Pad.
They both should work interchangeably since they essentially do the same
thing but often in different ways. An object could use Window, or Pad.

However, stuff like printing a border or writing a string onto the
window are essentially the same except that the offsets in Window are
absolute whereas the Pad offsets are relative. So when Pad calls super
it only has to make the relative offsets absolute:

def printstring(row, col, value, color, attrib=Ncurses::A_NORMAL)
super(row - @top, col - @left, value, color, attrib)
end # printstring

def print_border row, col, height, width, color,
att=Ncurses::A_NORMAL
super(row - @top, col - @left, height, width, color, att)
end

Now in the parent Window, print_border does a call to printstring to
reset the background. Unfortunately, the child's printstring gets called
and @top and @left get decremented again.

So why not just factor out what's different between Parent and Child

class Parent
def printstring(row, col, ... other parameters omitted)
row, col = *transform(row, col)
# do whatever you need
end

def transform(row, col)
[row, col]
end
end

class Child < Parent
def transform(row, col)
[row - @top, col - @left]
end
end

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

Rick Denatale wrote:

I'm having trouble understanding how you got into this position. �I'm

att=Ncurses::A_NORMAL
� � �super(row - @top, col - @left, height, width, �color, att)
� �end

Now in the parent Window, print_border does a call to printstring to
reset the background. Unfortunately, the child's printstring gets called
and @top and @left get decremented again.

So why not just factor out what's different between Parent and Child

class Parent
  def printstring(row, col, ... other parameters omitted)
      row, col = *transform(row, col)
      # do whatever you need
  end

  def transform(row, col)
     [row, col]
  end
end

class Child < Parent
   def transform(row, col)
       [row - @top, col - @left]
   end
end

Aah, there are more such methods.

SO in the second method print_border which happens to call printstring I
would save row, col for the next call.

class Parent
  def print_border(row, col, ... other parameters omitted)
- row, col = *transform(row, col)
+ nrow, ncol = *transform(row, col)
      # do whatever you need with nrow and ncol
+ printstring row, col # using original args
  end

Looks good, will give it a try. I feel there's still something "off" in
what i've done, and the question I am asking you, since it requires the
parent to protect itself from (or know of) misbehaviour from a child.

The overriding in Child was tacked on hastily and worked great till i
noticed some cases where an extra line was getting erased.

Thanks a lot.

···

On Mon, Feb 1, 2010 at 1:54 AM, R. Kumar <sentinel.2001@gmx.com> wrote:

--
Posted via http://www.ruby-forum.com/\.

Xavier Noëlle wrote:

If you are saying that aM() forces a call to the parent's m() and of
course you have inherited from Father, then yes.

Yes, my mistake, I forgot the "public Father".

def aM
�super.m
end

Yes, indeed, but what if I need to call a specific parent's method ?
Say Parent > Child > Grandchild. Is it possible to Parent::m in
Grandchild (other than super.super.m(), if it works :-)) ?

I doubt that that's possible in the way you want, since ruby is not
strictly typed, so this kind of type-casting won't work.
However, there could be ways using metadata- you'll have to wait for an
expert to answer.

Simple way:
put an explicit method in class such as grandpa_a or parent_a for the
one you want to call.
You could reopen the class and add the method where required.

Others:
Since you can get public methods of an object, i think you can go up the
heirarchy and get the specific method. And then pass your message to it
using send.
You could do a one time traversal and store a ref to the method.

Surely there will be other methods.

···

2010/2/5 R. Kumar <sentinel.2001@gmx.com>:

--
Posted via http://www.ruby-forum.com/\.

If you are saying that aM() forces a call to the parent's m() and of
course you have inherited from Father, then yes.

Yes, my mistake, I forgot the "public Father".

def aM
super.m
end

Yes, indeed, but what if I need to call a specific parent's method ?
Say Parent > Child > Grandchild. Is it possible to Parent::m in
Grandchild (other than super.super.m(), if it works :-)) ?

That idiom isn't well supported in Ruby, but it is possible
in an awkward sort of way:

$ cat sample.rb
class Parent
  def foo(*args)
    puts "Parent:foo: #{args.inspect}"
  end
end
class Child < Parent
  def foo(*args)
    super
    puts "Child:foo: #{args.inspect}"
  end

  def parent_foo(*args)
    Parent.instance_method('foo').bind(self).call(*args)
  end
end
$ irb

load 'sample.rb'

=> true

Parent.new.foo(1,2,3)

Parent:foo: [1, 2, 3]
=> nil

Child.new.foo(4,5,6)

Parent:foo: [4, 5, 6]
Child:foo: [4, 5, 6]
=> nil

Child.new.parent_foo(7,8,9)

Parent:foo: [7, 8, 9]
=> nil

Gary Wright

···

On Feb 5, 2010, at 10:33 AM, Xavier Noëlle wrote:

2010/2/5 R. Kumar <sentinel.2001@gmx.com>:

Xavier Noëlle wrote:

Yes, indeed, but what if I need to call a specific parent's method ?
Say Parent > Child > Grandchild. Is it possible to Parent::m in
Grandchild (other than super.super.m(), if it works :-)) ?

Besides the solution Gary Wright has shown, there's a simple solution:

class Parent
   def blah
     puts 'blah blah blah'
   end
   alias original_blah blah
end

Now, if some class inherits and overrides blah(), you can still call the
original blah() by doing original_blah().

···

--
Posted via http://www.ruby-forum.com/\.

This is probably the same as what Rick was saying...

If you own Parent, then the method I showed is definitely not what you
want to do. And, the solution does not require a special Ruby way,
just a refactor:
class Parent
  def printa arg
      puts "inside parent printa #{arg} "

    task_b arg #<-- problem solved, Parent#printa will always use the same version of printb

  end

  def printb arg

  task_b arg #<-- delegate work to an extracted method

  end

private
def task_b arg # Original implementation of Parent#printb is private helper method
  puts "inside parent printb #{arg} "
  puts "--> #{arg} "
end

end

Output:
parent calls with 5 and 6
inside parent printa 5
inside parent printb 5
--> 5
=== child calls with 7 ===
inside child printa 7 reduced 1
inside parent printa 6
inside parent printb 6
--> 6

Inheritance always introduces coupling between class and superclass.
The answer is to cover the code with tests, and run them in order to
ensure that the code works correctly when developed, and then to
detect any regressions.

The other think to watch out for in this particular case, is not to
confuse the implementation relationship of subclassing/module
inclusion with the containment relationship of windows/widgets. You
don't seem to be doing this from what you've posted, but ...

···

On Mon, Feb 1, 2010 at 10:10 AM, R. Kumar <sentinel.2001@gmx.com> wrote:

Looks good, will give it a try. I feel there's still something "off" in
what i've done, and the question I am asking you, since it requires the
parent to protect itself from (or know of) misbehaviour from a child.

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

Rick Denatale wrote:

The other think to watch out for in this particular case, is not to
confuse the implementation relationship of subclassing/module
inclusion with the containment relationship of windows/widgets. You
don't seem to be doing this from what you've posted, but ...

Not sure what you mean by what I've posted - do you mean the sample code
which was only illustrative since the actual code will not be runnable.
Or what i have later discussed... since in my case a Pad is a window and
is not contained in a window.
Where a Window was being used earlier, now a Pad may be used. However,
the user objects are unaware of whether they are writing to a Window or
a Pad.

I know there is one thing that is wierd about this. And that's that the
constructor of Window creates a ncurses window, whereas the constructor
of Pad creates a ncurses Pad. So the constructor of Pad does not do a
super. However, by subclassing i get all the behaviour of Window which
is essentially identical.

Sadly, i can't cover this with automated tests since its all visual and
the most errors can only be seen visually.

···

--
Posted via http://www.ruby-forum.com/\.

Sean DeNigris wrote:

This is probably the same as what Rick was saying...

If you own Parent, then the method I showed is definitely not what you
want to do. And, the solution does not require a special Ruby way,
just a refactor:
class Parent
  def printa arg
      puts "inside parent printa #{arg} "

    task_b arg #<-- problem solved, Parent#printa will always use the same version of printb

  end

  def printb arg

  task_b arg #<-- delegate work to an extracted method

  end

Ok, i get it, printa should not call printb since that goes thru the
inheritance chain. They should both call task_b in which the work has
been factored.

Thanks !!!

···

--
Posted via http://www.ruby-forum.com/\.

Sean DeNigris wrote:

This is probably the same as what Rick was saying...

If you own Parent, then the method I showed is definitely not what you
want to do. And, the solution does not require a special Ruby way,
just a refactor:

**Thanks**, all. I did a refactor of `printstring()` and it worked
straight off. Very clean.

···

--
rkumar
--
Posted via http://www.ruby-forum.com/\.