hiding vs. overriding

B

Bob Weiner

What is the purpose of hiding intead of overriding a method? I have googled
the question but haven't found anything that makes any sense of it.

In the code below, the only difference is that when the Poodle is upcast to
the Dog (in its wildest dreams) it then says "bow wow" where the bernard
always says "woof" (see code). Basically, it appears that I'm hiding the
poodle's speak method from everything except the poodle.

Why would I want to do this?
bob

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


class Pets {
[STAThread]
static void Main(string[] args) {
Bernard b = new Bernard();
Poodle p = new Poodle();

b.speak();
p.speak();

((Dog)b).speak();
((Dog)p).speak();

pause();
}

static void pause() {
Console.Write("\npaused");
Console.ReadLine();
}
}

class Dog {
public virtual void speak() { print("bow wow"); }

protected void print (string msg) {
Console.WriteLine( "{0}: {1}\n", this.GetType().ToString(), msg);
}
}

class Bernard : Dog {
public override void speak() { print("woof"); }
}
class Poodle : Dog {
public new void speak() { print("yip yip yip yip yip yip yip yip yip
yip"); }
}
 
N

Nicholas Paldino [.NET/C# MVP]

Bob,

Quite honestly, I can't see the reason one would want to do this. I
haven't found a truly GOOD reason yet to use method hiding, and I eschew
it's use.

Hope this helps.
 
B

Bob Weiner

Not the answer I was expecting but it is good to hear. I thought I was
missing something big.

Thanks,
bob



Nicholas Paldino said:
Bob,

Quite honestly, I can't see the reason one would want to do this. I
haven't found a truly GOOD reason yet to use method hiding, and I eschew
it's use.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Bob Weiner said:
What is the purpose of hiding intead of overriding a method? I have
googled the question but haven't found anything that makes any sense of
it.

In the code below, the only difference is that when the Poodle is upcast
to the Dog (in its wildest dreams) it then says "bow wow" where the
bernard always says "woof" (see code). Basically, it appears that I'm
hiding the poodle's speak method from everything except the poodle.

Why would I want to do this?
bob

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


class Pets {
[STAThread]
static void Main(string[] args) {
Bernard b = new Bernard();
Poodle p = new Poodle();

b.speak();
p.speak();

((Dog)b).speak();
((Dog)p).speak();

pause();
}

static void pause() {
Console.Write("\npaused");
Console.ReadLine();
}
}

class Dog {
public virtual void speak() { print("bow wow"); }

protected void print (string msg) {
Console.WriteLine( "{0}: {1}\n", this.GetType().ToString(), msg);
}
}

class Bernard : Dog {
public override void speak() { print("woof"); }
}
class Poodle : Dog {
public new void speak() { print("yip yip yip yip yip yip yip yip yip
yip"); }
}
 
J

Jay B. Harlow [MVP - Outlook]

Bob,
I use hiding primarily for version control.

For example I release V1 of my type that inherits from base. My type has a
SpecificMethod, where as base does not.

Along comes version 2 of base & it adds a SpecificMethod that is
incompatible with my type's SpecificMethod. Hiding ensures that my types
SpecificMethod does not wreak havoc with base's SpecificMethod & visa versa,
with out me needing to do some serious refactoring to my V2 of my type to be
compatible with V2 of base.


The other place I use hiding is for adding Attributes to properties of
controls in Windows Forms. For example changing the default
(DefaultAttribute) on non-overridable Properties of controls... In this case
I ensure my property simply calls the base property...

Hope this helps
Jay

| What is the purpose of hiding intead of overriding a method? I have
googled
| the question but haven't found anything that makes any sense of it.
|
| In the code below, the only difference is that when the Poodle is upcast
to
| the Dog (in its wildest dreams) it then says "bow wow" where the bernard
| always says "woof" (see code). Basically, it appears that I'm hiding the
| poodle's speak method from everything except the poodle.
|
| Why would I want to do this?
| bob
|
| -------------------------------------------------------------------------------------
|
|
| class Pets {
| [STAThread]
| static void Main(string[] args) {
| Bernard b = new Bernard();
| Poodle p = new Poodle();
|
| b.speak();
| p.speak();
|
| ((Dog)b).speak();
| ((Dog)p).speak();
|
| pause();
| }
|
| static void pause() {
| Console.Write("\npaused");
| Console.ReadLine();
| }
| }
|
| class Dog {
| public virtual void speak() { print("bow wow"); }
|
| protected void print (string msg) {
| Console.WriteLine( "{0}: {1}\n", this.GetType().ToString(), msg);
| }
| }
|
| class Bernard : Dog {
| public override void speak() { print("woof"); }
| }
| class Poodle : Dog {
| public new void speak() { print("yip yip yip yip yip yip yip yip yip
| yip"); }
| }
|
|
 
C

Chad Z. Hower aka Kudzu

Nicholas Paldino said:
Quite honestly, I can't see the reason one would want to do this. I
haven't found a truly GOOD reason yet to use method hiding, and I eschew
it's use.

There are useful cases of hiding, but they are rare. In fact I didnt reply to this earlier as I could not
think of a good examle. But I have run across them and used it before.


--
Chad Z. Hower (a.k.a. Kudzu) - http://www.hower.org/Kudzu/
"Programming is an art form that fights back"

Empower ASP.NET with IntraWeb
http://www.atozed.com/IntraWeb/
 
N

Nicholas Paldino [.NET/C# MVP]

haha, sorry, but it's kind of like saying "Yes, bigfoot exists, but I
have never seen him."

It's nothing personal, and I'm not putting down the post, it just made
me laugh when I read it.
 
C

Chad Z. Hower aka Kudzu

Nicholas Paldino said:
haha, sorry, but it's kind of like saying "Yes, bigfoot exists,
but I
have never seen him."

Oh no, I've seen him. ;) I just cant remember where right now. Im sure I could dig through my archives
and find the pictures - but to be honest Im not going to spend 30 minutes or more digging up info for a
newsgroup reply....
It's nothing personal, and I'm not putting down the post, it just
made
me laugh when I read it.

Understood. ;)


--
Chad Z. Hower (a.k.a. Kudzu) - http://www.hower.org/Kudzu/
"Programming is an art form that fights back"

Make your ASP.NET applications run faster
http://www.atozed.com/IntraWeb/
 
M

Michael S

Bob Weiner said:
Not the answer I was expecting but it is good to hear. I thought I was
missing something big.

Hi Bob.
I think you are missing something big. Something enormous.
I'm thinking about performance and versioning.

This entire topic is why most Delphites think of C# and .NET as a
Delphi-derived platform and not a Java rip-off. The only thing .NET has in
common with Java is the Object class. Delphites understand .NET from day one
while Javaites have some learning to do. Anders Hjelsberg choosed to realize
the default-non-virtual model from Delphi into .NET.

Consider Java. Java methods comes in two flawors; (implicit) virtual and
(explicit) final. Hence all methods are virtual if you don't mark them as
final. This is why Java has no 'override' keyword. If a subclass introduces
the method Foo() and that method exists in any superclass you override it.
Period.

This is dangerous when it comes to versioning. I might give you a class 1.0
with 10 methods and you choose to subclass it with 5 methods. Then I release
a 1.1 version of my cool and useful class, but I've added 3 methods and one
of them has the same name as one of yours.

Without your knowledge you have just overidden a method. As there are no
explicit overriding mechanism in Java, the compiler will happily compile and
override. The problems and obscure bugs from this scheme is two-folded. Your
method is now part of a polymorphic behaviour without support for it. When
my code calls my method your method gets called. Your method will
(obviously) not call on super() and hence my important code will not get
executed. My method might change the object state and then assume that some
actions where committed (that was not executed). Do you see the problem?

This is a serious design-flaw in the Java language and this is why we see so
little inheritance in Java. Javaites tend to use final classes that derives
from object or beans in conjunction with interfaces to protect themselves
from these kind of unwanted overriding.

Also, virtual methods are not good for performance. A virtual method cannot
be statically linked. Whenever you call on a virtual method you have a level
of indirection as the runtime has to check what type the object really is
and call it's method. More on this below.

Delphi and .NET have solved this problem gracefully by including a third
mode that is default. Non-virtual methods. With non-virtual methods we are
no longer afraid of subclassing. Just compare TForm in Delphi 1.0 and Delphi
7.0 and you can see that Borland is not afraid of having many superclasses
and adding a lot of stuff to them. Same is true for .NET as it is nothing
but a rip-off from VCL and WFC. Not sure if it can be called a rip-off as
Hjelsberg was involved in all three of them.

Anyways, as methods are non-virtual by default the compiler can statically
link a method at compile-time. This is done by the JITer. An example:

MySuperClass o = new MySubClass();
o.DoStuff(); // method is non-virtual and the method in MySuperClass will be
called without hesitation. This is fast.
o.DoMyOverriddenStuff() //method is virtual and runtime have to check and
realize that o is typeof MySubClass and call the correct method. This hurts.

Now for some funny facts. The jitter in Java actually do support non-virtual
methods. The java runtime marks all leaf-classes (classes that have no
subclasses) and call on methods non-virtual. This is why the java runtime is
so much faster these days compared to older runtimes. The difference is that
..NET sport non-virttuality in the language while Java does not.

Now for your question about why you have to reintroduce non-virtual methods.
This is just to protect you from the flaws in Java. Virtual methods can be
overriden or reintroduced. Non-virtual methods can only be reintroduced.
Delphi actually uses the keyword 'reintroduce' while C# reuses the keyword
'new'. If you fail to do so; in Delphi you get a warning, in C# you get an
compile error. I like the latter.

This is a great safety-net. Whenever a subclass sports the same method as a
method in a superclass you cannot compile until you accept that. You can
reintroduce the method and if it's virtual you can override it. But the
great thing is that you have to respond and make a choice.

Then what is the correct choice?

Well, I think that reintroducing a method is a bad thing. If a superclass
wanna DoStuff() and your subclass wanna DoStuff() and these thingies are
different things; you don't wanna reintroduce stuff but rename your method
into DoThings().

My conclusion: Never ever reintroduce methods, but love the compiler for
stopping you from unwanted polymorphism and the weird bugs that follows.

Happy Coding
- Michael S
 
M

Michael S

Nicholas Paldino said:
haha, sorry, but it's kind of like saying "Yes, bigfoot exists, but I
have never seen him."

It's nothing personal, and I'm not putting down the post, it just made
me laugh when I read it.

What? You haven't seen Bigfoot? I see him all the time, and I'm beginning to
think he's stalking me. My doctor keeps adding pills to my prescription but
the hairy giant refuse to go away! Oh, wait.... My Bad.... I was thinking
about Visual Basic. =)

Anyways, reintroduction of methods is not important in .NET. As references
to classes are not polymorphic. In Delphi we have type of object, which is a
typed reference to a class which gives a (weird) boost to polymorphism.
Delphites overrides .Free and reintroduces .Create all the time.

But as classes are very much static in .NET, and won't polymorph on
class-level; reintroduction is of lesser use. See my post on performance and
versioning. However, the 'new' keyword on methods is of little use in .NET.
It must be there to make the system complete, but you're not supposed to use
it.

Don't use it!

Happy Asylum
- Michael S
 
C

Chad Z. Hower aka Kudzu

Michael S said:
boost to polymorphism. Delphites overrides .Free and reintroduces
.Create all the time.

And so do C#'ers. Overridding constructors is automatic. Delphi just appears to handle it
differently, but not as differently as you think.

Free, thats not a Delphi thing. C++ can override the destructor and so can other languages. Its just
that .NET doesnt have even a concept of Free, it uses finalize and dispose which are totally
different.
But as classes are very much static in .NET, and won't polymorph on
class-level; reintroduction is of lesser use. See my post on
performance and versioning. However, the 'new' keyword on methods is
of little use in .NET. It must be there to make the system complete,
but you're not supposed to use it.

Thats not true - there are still cases its useful. One is for consistency.

Base
Foo (Class)

Derived1
new Foo : base foo

Derived2
new Foo : base foo

Now I can use Derived1.Foo to accesst teh derived, Derived2.Foo, etc. ITs very consistent. If you
want to see what a mess it is without using it, see the generation for a typed dataset.
MyDS.MyTableRow xRow = xDS.MyTable.NewMyTableRow() .......


--
Chad Z. Hower (a.k.a. Kudzu) - http://www.hower.org/Kudzu/
"Programming is an art form that fights back"

Empower ASP.NET with IntraWeb
http://www.atozed.com/IntraWeb/
 
T

Tedb

I have seen a lot of opinions about not using method hiding. I am fairly
new to C# and inheritence in general.

The current project that I am working on involves using the SerialPort
class. My class is inheriting it to extend it with some custom
functionality. One of the tasks that I was hoping to do was to overload the
void Open() method with a bool Open() method that incorporated a Try/Catch
block to simply return with current port status, instead of raising an error
if it could not open the port. However when I try do that, I get a compiler
warning that I need to use the new modifier to hide the original void Open()
method. I am guessing that is because I am changing the return type of the
method, being new to this I will have to some reading to find out. Anyways,
at this point it looks like that my only option.

Does this situation still fall into the catagory of being a bad idea to use
'new'?



Ted
 
M

Michael S

Chad Z. Hower aka Kudzu said:
Thats not true - there are still cases its useful. One is for consistency.

Yep. You are right and I rest my case. Thanks.

Happy Coding
- Michael S
 
M

Michael S

Tedb said:
I have seen a lot of opinions about not using method hiding. I am fairly
new to C# and inheritence in general.

You'll get the hang of it. I can tell as you ask and just don't do.
The current project that I am working on involves using the SerialPort
class. My class is inheriting it to extend it with some custom
functionality.

Sounds like fun. But have you consider wrapping it?
I hate to sound like a Javait, but most often a wrapper will do the trick.
One of the tasks that I was hoping to do was to overload the
void Open() method with a bool Open() method that incorporated a Try/Catch
block to simply return with current port status, instead of raising an
error
if it could not open the port.

The return value is not part of a method signature and as such, you are not
overloading.
However when I try do that, I get a compiler
warning that I need to use the new modifier to hide the original void
Open()
method. I am guessing that is because I am changing the return type of
the
method, being new to this I will have to some reading to find out.
Anyways,
at this point it looks like that my only option.

Yep. The compiler gets mad at you becasuse your not overloading. Nor are you
overriding.
Does this situation still fall into the catagory of being a bad idea to
use
'new'?

Yes. It does. This is a textbook example when not to use inheritance.

I would recommend that you create a new class that wraps your file class. It
may call .Open(..) and return a bool. Don't inherit for no reason. And it's
ok to name the class FileManagaer, even though it will make oo-purists mad
like hell. *s*

I've seen this.. seen this way too often. Just because the feature is there,
it doesn't mean you have to use it. People do inheritance for no reason.
People do properties for fields that does no valdiation. People implement
interfaces without any effect whatsoever. I call these people lame coders. I
don't hire them, and if I do by accident; I'll teach them how to be
prospereous while taking maintaince into account.

May I cite Eienstein (bet he said it in german):
- Keep it as simple as possible, but no simpler!

I'm not calling you a lame coder TedB.. atleast not yet...

Happy Coding
- Michael S
 
T

Tedb

Thanks for the feedback, this is an existing VB6 project that I am
converting to C# for the learning experience. In VB6 the serial port object
(MSComm) is currently wrapped, so I am in fact looking at wrapping vs
inheriting. Wrapping means that I need to add code for all of the methods
and properties that need to be exposed from the SerialPort class (PortName,
BaudRate, DataBits, StopBits, etc...) plus the extra five or six functions
that I want to add. Inheriting would give me all of the SerialPort
functions and I would just have to add the five or six extra functions. To
me (newbie) it seemed like a natural fit for inheritance (minus the Open()
method issue). Oh well, it just looks like I need to do some more reading
on the subject.
 
J

Jon Skeet [C# MVP]

Michael S said:
I think you are missing something big. Something enormous.
I'm thinking about performance and versioning.

This is a serious design-flaw in the Java language and this is why we see so
little inheritance in Java. Javaites tend to use final classes that derives
from object or beans in conjunction with interfaces to protect themselves
from these kind of unwanted overriding.

I agree that it's a design flaw, but I don't think it's something which
tends to affect the design of Java class libraries. (I personally avoid
inheritance for entirely separate reasons - a class which is designed
to be inherited from requires *much* more careful design and
documentation, and the implementation becomes less flexible, as public
methods can't call themselves with quite so much impunity.)

Fortunately with Java 1.5 (or 5.0, depending on who you talk to)
there's the @Override annotation, which while it has no impact on the
generated code (as far as I can see) does at least let a compiler warn
you if you're trying to override something and failing, or if you're
not aware that you're overriding something. Of course, it doesn't help
in versioning terms - it only helps at compile time. Better than
nothing though :)
Also, virtual methods are not good for performance. A virtual method cannot
be statically linked. Whenever you call on a virtual method you have a level
of indirection as the runtime has to check what type the object really is
and call it's method. More on this below.

That doesn't actually have much effect in modern Java VMs, as you
mentioned. In fact, it's quite nice that Java VMs can have a method
which *can* be overridden but won't usually be, without the normal
performance hit of a virtual method.
 
M

Michael S

Jon Skeet said:
I agree that it's a design flaw, but I don't think it's something which
tends to affect the design of Java class libraries. (I personally avoid
inheritance for entirely separate reasons - a class which is designed
to be inherited from requires *much* more careful design and
documentation, and the implementation becomes less flexible, as public
methods can't call themselves with quite so much impunity.)

I've was hoping you'd post. Thanks for being here.
I think it does affect and effect the java class libraries.
And I think 'serious design-flaw' is more describing than just
'design-flaw'.

Fortunately with Java 1.5 (or 5.0, depending on who you talk to)

LOL. Both Microsoft and Borland must have had a great laugh when Sun tried
to pull that stunt in being modern.
there's the @Override annotation, which while it has no impact on the
generated code (as far as I can see) does at least let a compiler warn
you if you're trying to override something and failing, or if you're
not aware that you're overriding something. Of course, it doesn't help
in versioning terms - it only helps at compile time. Better than
nothing though :)

Yep. Better than nothing. But still lame and a workaround.
That doesn't actually have much effect in modern Java VMs, as you
mentioned. In fact, it's quite nice that Java VMs can have a method
which *can* be overridden but won't usually be, without the normal
performance hit of a virtual method.

Yes. But you're just repeating what I just said in different words. I think
this is a workaround and a serious flaw. What do you really think?
Jon Skeet - <[email protected]>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Mr. Skeet. I always like your posts and your insights. We don't always
agree, which I also like, but this time it felt too easy. Do you have an ace
up your sleeve or are you just bored?

Happy Thoughts
- Michael S
 
J

Jon Skeet [C# MVP]

Michael S said:
I've was hoping you'd post. Thanks for being here.
I think it does affect and effect the java class libraries.

I think we'll have to agree to disagree. I think there are far better
reasons to avoid inheritance than due to accidental overriding. After
all, it's fairly easy to make methods final if you want to. I think
that the "favour composition over inheritance" pattern has had more
influence. In fact, there are some places where Java should definitely
have used that pattern, but didn't - java.util.Properties is the most
obvious one, which should have been *composed* of a HashTable rather
than extending it. The problems I've had due to that design decision
(when I wanted to subclass Properties myself) helped me to form my view
on just why inheritance can be so dangerous :)
And I think 'serious design-flaw' is more describing than just
'design-flaw'.

Okay, I'd be happy to call it a serious design flaw if that helps :)
LOL. Both Microsoft and Borland must have had a great laugh when Sun tried
to pull that stunt in being modern.

It's not like it was the first time, either. They saw the mess with
Java 1.2/2.0, but *still* went ahead and mucked things up again. Oh
well...
Yep. Better than nothing. But still lame and a workaround.
Sure.


Yes. But you're just repeating what I just said in different words.

Not *quite*. I think it's a workaround which has beneficial side-
effects. (In other words, the need for inlining etc on theoretically
virtual methods forced Sun into an incremental JIT, which has numerous
benefits, with the drawback of being very complicated to implement in
the first place.)
I think this is a workaround and a serious flaw. What do you really think?

I think it's a flaw in the language, although one which hasn't affected
me very much in practice. I can't remember ever actually being bitten
by it - not that means it hasn't happened to other people, of course,
but I don't remember ever overriding something accidentally.
Mr. Skeet. I always like your posts and your insights. We don't always
agree, which I also like, but this time it felt too easy. Do you have an ace
up your sleeve or are you just bored?

I think we're just not disagreeing much, just on the severity of the
problem and the impact it's had. It's one of the areas where C#
definitely has the upper hand on Java. I don't think it's quite as much
of a problem as you do - not in practice.

(There are far better pot-shots to take at Java, in terms of the
language, the VM and the class library. The same is true of .NET, of
course - there's no perfect platform yet :)
 

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

Top