Sealed method can be overriden

Hi guys,

I’m trying to override a sealed method in IR and I succeed.

For example:
C#:
public class Shape
{
public virtual int GetNumberOfSizes() { return 0; }
}
public class Square : Shape
{
public override sealed int GetNumberOfSizes() { return 4; }
}

IR:
class NewSquare < Square
def get_number_of_sizes
return 99
end
end
puts NewSquare.new.get_number_of_sizes # => 99

Bug or by design?

Thanks,
Shay.

Shay F.
http://www.ironshay.com
Follow me: http://twitter.com/ironshay

You’ll be able to override anything in ruby - you’ll find CLR classes
harder
to fool.
Try creating a C# method that accepts a Shape and calls
the GetNumberOfSizes() method - I expect you’ll find that the NewSquare
override is ignored and the Square method is called instead.

I was surprised to find that a non virtual property in a C# class was
able
to be replaced by defining a new one in ruby (this was not the case for
a
non virtual method) - see

Mark.

Is there something special that needs to be done when overriding CLR
methods (like C#'s override keyword)?

In your example, you’re not overriding the sealed method (since it is
sealed :)). You’re defining a new method on the subclass. You can do
this in C# too:

class NewSquere : Square {
public new int GetNumberOfSizes() {
return 99;
}
}

As the “new” keyword suggest this method doesn’t share the v-table slot
with the base class method - it has its own new slot. Hence no virtual
call on NewSquare instance strongly typed to Shape or Square will call
your method.

Tomas

From: [email protected]
[mailto:[email protected]] On Behalf Of Mark R.
Sent: Saturday, June 13, 2009 1:37 AM
To: [email protected]
Subject: Re: [Ironruby-core] Sealed method can be overriden

You’ll be able to override anything in ruby - you’ll find CLR classes
harder to fool.

Try creating a C# method that accepts a Shape and calls the
GetNumberOfSizes() method - I expect you’ll find that the NewSquare
override is ignored and the Square method is called instead.

I was surprised to find that a non virtual property in a C# class was
able to be replaced by defining a new one in ruby (this was not the case
for a non virtual method) - see

Mark.

On Sat, Jun 13, 2009 at 6:22 PM, Shay F.
<[email protected]mailto:[email protected]> wrote:
Hi guys,

I’m trying to override a sealed method in IR and I succeed.

For example:
C#:
public class Shape
{
public virtual int GetNumberOfSizes() { return 0; }
}
public class Square : Shape
{
public override sealed int GetNumberOfSizes() { return 4; }
}

IR:
class NewSquare < Square
def get_number_of_sizes
return 99
end
end
puts NewSquare.new.get_number_of_sizes # => 99

Bug or by design?

Thanks,
Shay.

And also - with regular methods (not abstract, virtual sealed or
whatever), when I inherit them in IR - are the just hidden like the
static methods?

Thanks!
Shay.

Shay F.
http://www.ironshay.com
Follow me: http://twitter.com/ironshay

Yes, sealed virtual and “regular” methods have the same behavior.

Tomas

There is a slight difference though.
In the example:
puts NewSquare.new.get_number_of_sizes # => 99
puts NewSquare.new.GetNumberOfSizes # => 4

If I change the example to a regular method (not sealed), the output is
slightly different:
puts NewSquare.new.get_number_of_sizes # => 99
puts NewSquare.new.GetNumberOfSizes # => 99

Thanks,
Shay.


Shay F.
http://www.ironshay.com
Follow me: http://twitter.com/ironshay

No. We override the method if there is a non-sealed virtual in the base
class that has the same or un-mangled name.

Tomas

That’s expected. If you change “sealed override” to just “override” the
method is virtual and Ruby subclasses will override it.
In both cases NewSquare.new.GetNumberOfSizes finds CLR method
Square::GetNumberOfSizes and invokes it. In the first case, the method
is not overridden and therefore the implementation in Square gets
executed. Without “sealed” the method is overridden by
NewSquare#get_number_of_sizes and therefore the virtual dispatch
executes NewSquare’s implementation.

In both cases NewSquare.new.get_number_of_sizes finds Ruby method
NewSquare#get_number_of_sizes and executes it.

Tomas

The same happens with non-virtual methods as well.

By the way, should you be able to call super when you override a virtual
method?

Thanks,
Shay.


Shay F.
http://www.ironshay.com
Follow me: http://twitter.com/ironshay

Yes, super should work if the calling method is in a Ruby base class.

C#:
public class C {
public virtual int FooBar() { return 123; }
}

Ruby:
class D < C
def foo_bar
10 * super
end
end

p D.new.FooBar
p D.new.foo_bar

(there is a bug in the current bits that makes it throw an exception:
`get_MethodHandle’: The requested operation is invalid for
DynamicMethod. (TypeError), I’ll fix it asap).

Tomas

C#:
public class C {
public int FooBar() { return 123; }
}

Ruby:
require ‘x.dll’

class D < C
def foo_bar
48
end
end

p D.new.FooBar # => 123
p D.new.foo_bar # => 48

The same rules hold here: foo_bar does NOT override FooBar (since FooBar
is not virtual) and therefore is an unrelated method.
So the first call resolves to C::FooBar and invokes it.
The second call resolves to D#foo_bar and invokes it. Only if there
wasn’t foo_bar or FooBar defined in D this call would resolve to
C::FooBar.

Tomas

Thanks so much for the answers Tomas!


Shay F.
http://www.ironshay.com
Follow me: http://twitter.com/ironshay