Inheritance issue with new

  • Thread starter Thread starter gkrish
  • Start date Start date
G

gkrish

using System;

public class Animal
{
public string Sleep() { return "Animal::Sleep"; }
}

public class Fish : Animal
{
new public string Sleep() { return "Fish::Sleep"; }


[STAThread]
static void Main(string[] args)
{
Animal objFish = new Fish();
Console.WriteLine(objFish.Sleep());

}
}

In the above case I still get "Animal::Sleep" in the output but I expected
Fish:Sleep on account of the modifier new.
Can anyone explain ?

Thanks
GK
 
gkrish said:
In the above case I still get "Animal::Sleep" in the output but I
expected Fish:Sleep on account of the modifier new.
Can anyone explain ?

This is a misunderstanding of how the 'new' operator works. Quoting
from "Microsoft Visual C#.NET" by Mickey Williams, Chapter 2:

"After a method is declared as virtual in a base class, a subclass
indicates its intent to override the base class version of the class by
using the 'override' keyword"

and

"In C#, the 'new' keyword is used to hide a virtual base class
method. When a method is declared as 'new', the compiler is notified
that this method doesn't participate when looking for a virtual
method..."

Your code functions correctly if you change to:

using System;

public class Animal
{
public virtual string Sleep() { return "Animal::Sleep"; }
}

public class Fish : Animal
{
public override string Sleep() { return "Fish::Sleep"; }
}

public class X
{
static void Main(string[] args)
{
Animal objFish = new Fish();
Console.WriteLine(objFish.Sleep());
Console.ReadLine();
}
}

which outputs 'Fish::Sleep'.

-mdb
 
the declared type of objFish is still Animal and there's no override if the Sleep method in Fish clas
so the Sleep in Animal class gets calle

the new Sleep method in Fish class is completely irrelevant in this cas
unless you g

Fish objFish = new Fish()
objFish.Sleep();
 
...
using System;

public class Animal
{
public string Sleep() { return "Animal::Sleep"; }
}

public class Fish : Animal
{
new public string Sleep() { return "Fish::Sleep"; }


[STAThread]
static void Main(string[] args)
{
Animal objFish = new Fish();
Console.WriteLine(objFish.Sleep());

}
}

In the above case I still get "Animal::Sleep" in the
output but I expected Fish:Sleep on account of the
modifier new.
Can anyone explain ?

It's because "new" doesn't make the method "override" the inherited one, as
it would if you used virtual methods for "dynamic binding".

With "new", you create a method that can "hide" the former, but only in the
scope of "Fish"-variables, but as you declared objFish as an "Animal", it's
still that method that will be called.
Animal objFish = new Fish();

If you instead had declared the variable as a "Fish", you'd gotten the
"Fish"-result:

Fish objFish = new Fish();
Console.WriteLine(objFish.Sleep());

If you want dynamic binding, "truly overriding" the inherited method, you
have to make it "virtual", and explicitly override it.

public class Animal
{
public virtual string Sleep()
{ return "Animal::Sleep"; }
}

public class Fish : Animal
{
public override string Sleep()
{ return "Fish::Sleep"; }
}

// Bjorn A
 
Michael Bray said:
which outputs 'Fish::Sleep'.

oh... a bit more clarification... if you simply change

public class Fish : Animal
{
override public string Sleep() { return "Fish::Sleep"; }
}

to

public class Fish : Animal
{
new public string Sleep() { return "Fish::Sleep"; }
}

then it outputs "Animal::Sleep", which is what "new" does. The "new"
keyword is really misleading - it kind of does the opposite of what you
would think.

-mdb
 
gkrish said:
using System;

public class Animal
{
public string Sleep() { return "Animal::Sleep"; }
}

public class Fish : Animal
{
new public string Sleep() { return "Fish::Sleep"; }


[STAThread]
static void Main(string[] args)
{
Animal objFish = new Fish();
Console.WriteLine(objFish.Sleep());

}
}

In the above case I still get "Animal::Sleep" in the output but I expected
Fish:Sleep on account of the modifier new.
Can anyone explain ?

Yes - it's *precisely* because you used the modifier "new" instead of
making sleep virtual and using the *override* modifier.

See http://www.pobox.com/~skeet/csharp/faq/#override.new for more
information.
 
Back
Top