This is more or less an exact duplicate of this post, but as I cannot edit it, I started this. Feel free to move something over and close this one.
Using method hiding with new seems like a dangerous feature, and given the discussion in the other thread, it seems it's not only I who have problems finding a valid use case for this. Any methods accepting Base won't use Derived's Method.
public class Base
{
public void Method()
{
Console.WriteLine("Base");
}
}
public class Derived : Base
{
public new void Method()
{
Console.WriteLine("Derived");
}
}
var derived = new Derived();
derived.Method(); // "Derived"
((Base)derived).Method(); // "Base"
So what are some valid use cases for new that is difficult to solve with other features?
The idea is to avoid the brittle base class problem as far as possible.
Suppose you provide a library, and I derive from one of your classes. I create my own method, Foo(), and call it appropriately. Fine.
Now you introduce a second version of your library, and you add the Foo() method (with the same signature) to the base class. Now your code will call Foo(), which has one particular meaning... and that may be a completely different meaning to my Foo() method. The default behaviour (and the behaviour if you add the new modifier) is for things to behave as they should: code which only knows about the base class will call your method - which is fine, as that's what they mean. Code which uses an expression which has a compile-time type of my derived class will use my method - and that's fine, as that's what they should mean as well. (Basically it can only be my code, because only my code knows about my class.)
It should usually be avoided - it can lead to subtle bugs where changing the compile-time type of the variable silently changes the behaviour... but it's present for that sort of situation. Basically, adding a method to a base class shouldn't break derived classes, as far as possible.
Related
One thing i need to be clear. When using inheritance i can override a method without using any virtual or override keyword. My program also running and giving correct output. Then why do we have override concept even though we have inheritance. How it differs?
here is my code
class InheritanceDemo
{
public void Mymeth()
{
Console.WriteLine("this is base");
}
}
class A1 : InheritanceDemo
{
public void Mymeth()
{
Console.WriteLine("this is derived");
}
}
Main method:
static void Main(string[] args)
{
InheritanceDemo a = new A1();
A1 b = new A1();
a.Mymeth();
b.Mymeth();
}
output:
this is base
this is derived
Function overriding is needed when the derived class function has to do more or different job than the base class function.
These concepts becomes important in large scale application where problem is big so, u first create an abstract class (which just gives the ideas about how things might be rather than the direct implementation). These Abstract class can contain virtual methods (member functions) that any member of group working on has to implement (as virtual methods have to be defined in the derived class).
I think u got my point... :)
Why do you think the output is "correct"? With inheritance you want to call the correct inherited function and not a method in your base class. And that's what you define with virtual/override.
When you compiled this you should have got a warning CS0108.
Do not ignore warnings. Indeed, if you can set your compilation to error rather than warn. Warnings are generally a sign that you've done something bad or at best unclear. They aren't errors because you might have a good reason for doing something that looks bad or unclear at first look, but in the case of hiding instead of overriding we have new.
What you have here is not an override, though as you seem to expect, generally what you would want here is an override. That's part of why this code produces a compiler warning.
My program also running and giving correct output
Maybe it's correct, but it's not correct if you expected an override. If it was overriding you should have "this is derived" output by both.
If it is correct, it's a bad design, because people generally expect overrides. You can stop the warning by changing A1.Mymeth to be defined as public new void Mymeth() which is a way to flag "I really meant to do this thing that looks wrong", but if you have to explain yourself, that's a bad sign. Hiding methods is generally only to be done when someone changing a base class under you forces your hand, you need to match names due to some sort of interoperability and a small number of other very rare cases.
Today I had an interview where I have been asked
Is it possible to perform Method Hiding without using New keyword?
As far as I know , it is not possible. So I said that.
Is there any (seriously) tricky / alternate way to perform Method Hiding? I thought of Sealed once....
Also like Explicit Interface, is there something of that sort...(not sure)
Edited
As a last question on this topic, like we can do for explicit interface
Interfacename.Method name
Can we do something similar for a derived class like.
Class Derived:Base
{
public void Base.SomeMethod(){}
}
Absolutely - if you don't specify anything, you still get the same effect as with the new modifier, but you get a warning as well.
There's also explicit interface implementation, of course.
In both cases, just casting the target to a different type "unhides" the method:
((BaseClass) x).SomeMethod();
((IFoo) x).SomeMethod();
Sealing a class has nothing to do with method hiding though - or rather, it prevents any derived classes from hiding a method, by making sure there are no derived classes.
I've been searching for a while on this because I'm naturally forgetful and I thought it would be nice to build something (an abstract class, interface, etc.?) that would force me to implement certain bits of code in a class I was writing.
In particular, I would like to force a new class to always have a constructor that takes a single parameter typed as itself in order to make duplication of the object easier. I've seen articles/questions elsewhere that talk about this, but I'm not sure this particular question has been asked (at least that I can find) or I'm simply not understanding enough of the other articles/questions to realize it. My apologies in advance.
I'm not interested in having a constructor in an abstract class, interface, etc. actually do anything. I'm merely interested in defining the requirement for a constructor signature in a derived class.
My ideal class would look like this:
public class GoodClass
{
public GoodClass(GoodClass goodClass)
{
// copy components of goodClass to this instance
}
}
So, I first began researching interfaces and also started reading up on abstract classes. I was thinking something like the code below would work, but alas I get errors. Is what I'm trying to do even possible? Is there any other way I could accomplish my goal without putting a sticky note on my monitor? :)
abstract class SelfConstructor
{
abstract public SelfConstructor(SelfConstructor) { }
}
class NewClass : SelfConstructor
{
//Required by SelfConstructor:
public NewClass(NewClass newClass)
{
// copy components of newClass to this instance
}
}
You could write a ReSharper plugin that recognises this case and highlights the class if it doesn't have a "copy constructor". This would be a daemon stage that would process the file as it's being edited, and add highlights. You can look through the abstract syntax tree of the file, look for all instances of IConstructorDeclaration, and then get the constructor's parameters from the ParameterDeclarations property. You can check that there is a constructor that only has one parameter, and that parameter is the same type as the class it's declared in.
You can compare the types by getting the constructor's parameter's TypeUsage and trying to downcast to IUserTypeUsage. You can then use ScalarTypeName.Reference.Resolve() to get an instance of IDeclaredElement. Compare this against the class's IClassDeclaration.DeclaredElement to see if they're the same instance.
In C++, what you are talking about is a copy constructor, you actually get one by default!
C# doesn't have that concept (though of course you can define one); however, it is easier (and preferred) to simply implement ICloneable (MSDN), which requires you to implement the Clone method, that does the same thing.
Instead of:
object myObj = new CloneableObject(otherObj);
You write:
object myObj = otherObj.Clone();
The other thing you could do is force a constructor signature by not having a default:
public class BaseClass
{
//No abstract constructors!
public BaseClass(BaseClass copy)
{
}
}
Now when you derive, you have to use that overload in the constructor. Nothing will force the derived signature, but at least you have to explicitly use it:
public class DerivedClass : BaseClass
{
public DerivedClass() : base(this)
{
}
}
The above example clearly shows that it doesn't "force" you to have a copy constructor, but like a sticky note, would serve as a good reminder.
I would definitely go the interface route, as that is what is there for (and you can use an abstract implementation!).
Note that you can take advantage of Object.MemberwiseClone if you want a shallow copy for free. All objects get this, no interface required.
Why is it necessary to use the new keyword when a method shall be hidden?
I have two classes:
public class Parent
{
public void Print()
{
Console.WriteLine("Parent");
}
}
public class Child : Parent
{
public void Print()
{
Console.WriteLine("Child");
}
}
Following code produces the given output:
Parent sut = new Child();
sut.Print();
Output: Parent
Child sut = new Child();
sut.Print();
Output: Child
I understand that this might be a problem if it the hiding was not intended but is there any other reason to use "new" (excepted avoding of warnings)?
Edit:
May be I was not clear. It is the same situation like:
public void foo(Parent p)
{
p.Print();
}
which is called:
Child c = new Child;
foo (c);c
No, but avoiding the warnings is incredibly important. The bugs caused by hiding can be insiduous, and after C++ (which just let you do it) both Java and C# chose two different ways to prevent them.
In Java, it is not possible to hide a base classes methods. The compiler will scream bloody murder if you try to do it.
In C#, there is the "new" keyword. It allows you to be explicit that you want to hide a method, and the compiler will warn you if you are not using it. Many developers make it a rule to have code compiler with no warnings because warnings can be a sign of bad code.
After all that, I have never had to use hiding. I would carefully consider why I was even considering using it, since its behavior is strange and almost never what I want.
If you are trying to use inheritance, you should make the method virtual in the base class, and override it in the child class.
The language designers have decided that when these keywords are not used, then method hiding should be explicitly done with the new keyword.
Hiding is a bad idea. It makes code more confusing, and your intent is unclear. Programming languages are about expressing your intent to both the compiler and to other programmers. It is not clear without a new keyword whether your intent was to override or to hide, or if you were just ignorant of the base method.
There's also an element of foolproofing. "Shoot-self in foot. Are you sure? OK/Cancel".
The real question is why is hiding allowed in the first place. The problem with not allowing hiding, is that if you derive from a class in another assembly and add a Foo() method, and then that other assembly is updated to add a Foo() method, not allowing for hiding would break your code.
Expanding on what Jon Hanna said...
The point of the warning is to tell you there is a name clash you might not be aware of. When you get the warning, you should do one of the following:
Add virtual and override to polymorphically override the method from the base class
Rename your method so its name no longer clashes with the method in the base class
Add new to make clear your intention to hide the method
If you are extending or refining the behaviour of the method in the base class, use virtual and override, as others have said here.
If you have just written your method for the first time and discover you have a name clash you weren't aware of and it is not your intention to override, simply rename your method.
Option 1 or 2 is usually preferable. So when should you resort to option 3?
You use option 3 when the base class is not your code. You don't have the option to add a virtual to it. The typical scenario where you need the new goes like this:
You bought a third party library. It has an interesting class. You inherit from the class and add a new method that the original author didn't provide. So far, there's no hiding or overriding involved. Now you receive a version 2 of the library, with some new features you want to use. The authors have added a new method to their class, and its name clashes with a method you wrote in your derived class.
If your method is not used very much, you should rename it out of the way, option 2. But if there are many dependencies on your method, it would be very disruptive to rename it. So you add the new to say that there is no logical connection between your method and the one in the base class, even though they happen to have the same name. You don't have the ability to add a virtual to the method in the base class, nor do you want to do that. The two methods were designed by different developers and your method doesn't refine or extend the one in the base class - when you wrote yours, the one in the base class didn't exist.
So, it's rare that you need the new keyword, but when you do, it's important.
Because it makes it explicit that you are deliberately hiding the parent's method, rather than overriding it. There is a warning when you don't use new because your subclass's method may have a typo in it, and accidentally hiding a parent method can lead to some subtle bugs.
You will have to use the new keyword if the method with the same signature in the base class isn't marked with abstract or virtual.
Just mark the Parent's method virtual. Then you would do public override void Print() in your child class.
public class Parent
{
public virtual void Print()
{
Console.WriteLine("Parent");
}
}
public class Child : Parent
{
public override void Print()
{
Console.WriteLine("Child");
}
}
This way you get the real inheritance and you can call the parents Print() method from the Child by calling base.Print()
Why is it necessary to use the new keyword when a method shall be hidden?
It is not necessary. The only function of new here is to suppress the warning.
The question could be: Why is it not an error to hide base class members?
The answer to the addition to your question
May be I was not clear. It is the same
situation like:
public void foo(Parent p) {
p.Print(); } which is called:
Child c = new Child; foo (c);
The answer is the foo(c) will output Parent. The method that hides the parent method will not execute if you are calling the parent class as in the example. To get the output of Child you will need to use virtual and override as described in earlier answers.
You can check the details here why method hiding allowed and to the scope of it.
https://msdn.microsoft.com/en-us/library/aa691135(v=vs.71).aspx
I've found loads of practical examples of this, and understand the practical output when overriding or hiding methods, but I'm looking for some under the covers info on why this is and why C# allows it when according to the rules of polymorphism, this shouldn't be allowed - at least, insofar as my understanding of polymorphism goes (which seems to coincide with the standard definitions found on Wikipedia/Webopedia).
Class Base
{
public virtual void PrintName()
{
Console.WriteLine("BaseClass");
}
}
Class FirstDerived : Base
{
public override void PrintName()
{
Console.WriteLine("FirstDerived");
}
}
Class SecondDerived : Base
{
public new void PrintName()
{
Console.WriteLine("SecondDerived");
}
}
Using the following code:
FirstDerived b = new FirstDerived();
BaseClass a = b;
b.PrintName();
a.PrintName();
I get:
FirstDerived
FirstDerived
Okay, I get that, makes sense.
SecondDerived c = new SecondDerived();
BaseClass a = c;
c.PrintName();
a.PrintName();
I get:
SecondDerived
BaseClass
Okay, that makes sense, too, instance a can't see c.PrintName() so it's using its own method to print its own name, however I can cast my instance to its true type using:
((SecondDerived)a).PrintName();
or
(a as SecondDerived).PrintName();
to get the output I would expect:
SecondDerived
So what is going on under the covers and what does this mean in terms of polymorphism? I'm told that this facility "breaks polymorphism" - and I guess according to the definition, it does. Is that right? Would an "object oriented" langage like C# really allow you to break one of the core principles of OOP?
(This answers the "why is it allowed" which I think is really the central point of your question. How it works in terms of the IL is less interesting to my mind... let me know if you want me to go into that though. Basically it's just a case of specifying the method to call with a different type token.)
It allows base classes to evolve without breaking derived classes.
Suppose Base didn't originally have the PrintName method. The only way to get at SecondDerived.PrintName would be to have an expression with a static type of SecondDerived, and call it on that. You ship your product, everything is fine.
Now fast forward to Base introducing a PrintName method. This may or may not have the same semantics of SecondDerived.PrintName - it's safest to assume that it doesn't.
Any callers of Base.PrintName know that they're calling the new method - they couldn't have called it before. Any callers which were previously using SecondDerived.PrintName still want to use it though - they don't want to suddenly end up calling Base.PrintName which could do something entirely different.
The difficulty is new callers of SecondDerived.PrintName, who may or may not appreciate that this isn't an override of Base.PrintName. They may be able to notice this from the documentation of course, but it may not be obvious. However, at least we haven't broken existing code.
When SecondDerived is recompiled though, the authors will be made aware that there's now a Base.PrintName class through a warning. They can either stick to their existing non-virtual scheme by adding the new modifier, or make it override the Base.PrintName method. Until they make that decision, they'll keep getting a warning.
Versioning and compatibility isn't usually mentioned in OO theory in my experience, but C# has been designed to try to avoid compatibility nightmares. It doesn't solve the problem completely, but it does a pretty good job.
I answer "how" it works. Jon has answered the "Why" part.
Calls to virtual methods are resolved a bit differently to those of non-virtual ones. Basically, a virtual method declaration introduces a "virtual method slot" in the base class. The slot will hold a pointer to the actual method definition (and the contents will point to an overridden version in the derived classes and no new slot will be created). When the compiler generates code for a virtual method call, it uses the callvirt IL instruction, specifying the method slot to call. The runtime will dispatch the call to the appropriate method. On the other hand, a non-virtual method is called with a call IL instruction, which will be statically resolved to the actual method by the compiler, at compile time (only with the knowledge of the compile-time type of the variable). new modifier does nothing in the compiled code. It essentially tells the C# compiler "Dude, shut up! I'm sure I'm doing the right thing" and turns off the compiler warning.
A new method (actually, any method without an override modifier) will introduce a completely separate chain of methods (new method slot). Note that a new method can be virtual itself. The compiler will look at the static type of the variable when it wants to resolve the method chain and the run time will choose the actual method in that specific chain.
According to the Wikipedia definition:
Type polymorphism in object-oriented
programming is the ability of one
type, A, to appear as and be used like
another type, B
Later on the same page:
Method overriding is where a subclass
replaces the implementation of one or
more of its parent's methods. Neither
method overloading nor method
overriding are by themselves
implementations of polymorphism.
The fact that SecondDerived does not provide an override for the PrintName does not affect its ability to appear and be used as Base. The new method implementation it provides will not be used anywhere an instance of SecondDerived is treated as an instance of the Base; it will be used only when that instance is explicitly used as an instance of SecondDerived.
Moreover, SecondClass can actually explicitly implement the Base.PrintName in addition to the new hiding implementation, thus providing its own override that will be used when treated as Base. (Though, Base has to be an explicit interface definition or has to derive from one to allow this)