mardi 13 mai 2014

c# - confondu entre virtuel, substituer, nouveau et scellé substituer - Stack Overflow


I'm pretty confused between some concepts of OOPS: virtual, override, new and sealed override. Can anyone explain me about the same. Best would be giving an example or a link for the same.


I am pretty clear that if derived class method is to be used, one can use "override" keyword and hence base class method would be overriden by derived class.Am i correct?


But not sure about new, and sealed override.


Thanks!




The virtual keyword is used to modify a method, property, indexer or event declaration, and allow it to be overridden in a derived class. For example, this method can be overridden by any class that inherits it: Use the new modifier to explicitly hide a member inherited from a base class. To hide an inherited member, declare it in the derived class using the same name, and modify it with the new modifier.


This is all to do with polymorphism. When a virtual method is called on a reference, the actual type of the object that the reference refers to is used to decide which method implementation to use. When a method of a base class is overridden in a derived class, the version in the derived class is used, even if the calling code didn't "know" that the object was an instance of the derived class. For instance:


public class Base
{
public virtual void SomeMethod()
{
}
}

public class Derived : Base
{
public override void SomeMethod()
{
}
}

...

Base b = new Derived();
b.SomeMethod();

will end up calling Derived.SomeMethod if that overrides Base.SomeMethod.


Now, if you use the new keyword instead of override, the method in the derived class doesn't override the method in the base class, it merely hides it. In that case, code like this:


public class Base
{
public virtual void SomeOtherMethod()
{
}
}

public class Derived : Base
{
public new void SomeOtherMethod()
{
}
}

...


Base b = new Derived();
Derived d = new Derived();
b.SomeOtherMethod();
d.SomeOtherMethod();

Will first call Base.SomeOtherMethod , then Derived.SomeOtherMethod . They're effectively two entirely separate methods which happen to have the same name, rather than the derived method overriding the base method.


If you don't specify either new or overrides, the resulting output is the same as if you specified new, but you'll also get a compiler warning (as you may not be aware that you're hiding a method in the base class method, or indeed you may have wanted to override it, and merely forgot to include the keyword).


An overriding property declaration may include the sealed modifier. Use of this modifier prevents a derived class from further overriding the property. The accessors of a sealed property are also sealed.




Any method can be overridable (=virtual) or not. The decision is made by one who defines the method:


class Person
{
// this one is not overridable (not virtual)
public void GetPersonType()
{
return "person";
}

// this one is overridable (virtual)
public virtual String GetName()
{
return "generic name";
}
}

So now you can override those methods that are overridable:


class Friend : Person
{
public Friend() : this("generic name") { }

public Friend(String name)
{
this._name = name;
}

// now we override instance Person.GetName method:
public override String GetName()
{
return _name;
}
}

But you can't override GetPersonType method because it's not virtual. So now let's create two instances of those classes:


Person person = new Person();
Friend friend = new Friend("Onotole");

When non-virtual method GetPersonType is called by Fiend instance it's actually Person.GetPersonType that is called:


Console.WriteLine(friend.GetPersonType()); // "person"

When virtual method GetName is called by Friend instance it's Friend.GetName that is called.


Console.WriteLine(friend.GetName()); // "Onotole"

When virtual method GetName is called by Person instance it's Person.GetName that is called.


Console.WriteLine(person.GetName()); // "generic name"

When non-virtual method is called the method is not looked up - compiler always knows the actual method that needs to be called. With virtual methods compiler can't be sure which one to call, so it looks for it at runtime. When virtual method is called the actual method is looked up in the class hierarchy from down to up starting at the type of instance that the method is called on: for friend.GetName it looks starting at Friend class and finds it right away, for person.GetName class it starts at Person and finds it there.


Now sometimes you make a subclass, override a virtual method and you don't want any more overrides down in the hierarchy - you use sealed override for that (saying you are the last one who overrides this method):


class Mike : Friend
{
public sealed override String GetName()
{
return "Mike";
}
}

Now sometimes your friend Mike decides to change his gender and thus his name to Alice :) You could change code or subclass Mike:


class Alice : Mike
{
public new String GetName()
{
return "Alice";
}
}

Here you create a completely different method with the same name (so now you have two). So which method and when is called? It depends on how you call it:


Alice alice = new Alice();
Console.WriteLine(alice.GetName()); // the new method is called printing "Alice"
Console.WriteLine(((Mike)alice).GetName()); // the method hidden by new is called printing "Mike"

When you call it from Alice perspective you call Alice.GetName, when from Mike - you call Mike.GetName. And no lookup is made here. You can always create new methods - whether the methods you are hiding are virtual or not.


This applies to properties and events too - they generate methods underneath.




By default a method cannot be overridden in a derived class unless it is declared virtual, or abstract. virtual means check for newer implementations before calling and abstract means the same, but it is guaranteed to be overridden in all derived classes. Also, no implementation is needed in the base class because it is going to be re-defined elsewhere.


The exception to the above is the new modifier. A method not declared virtual or abstract can be re-defined with the new modifier in a derived class. When the method is called in the base class the base method executed, and when called in the derived class, the new method is executed. All the new keywords allows you to do is to have two methods with the same name in a class hierarchy.


Finally a sealed modifier breaks the chain of virtual methods and makes them not overridable again. This is not used often, but the option is there. It makes more sense with a chain of 3 classes each deriving from the previous one


A -> B -> C

if A has an virtual or abstract method, that is overridden in B, then it can also prevent C from changing it again by declaring it sealed in B.


sealed is also used in classes, and that is where you will commonly encounter this keyword.


I hope this helps.




Probably this is too obvious:





All keywords you can find here. There are examples 2.



I'm pretty confused between some concepts of OOPS: virtual, override, new and sealed override. Can anyone explain me about the same. Best would be giving an example or a link for the same.


I am pretty clear that if derived class method is to be used, one can use "override" keyword and hence base class method would be overriden by derived class.Am i correct?


But not sure about new, and sealed override.


Thanks!



The virtual keyword is used to modify a method, property, indexer or event declaration, and allow it to be overridden in a derived class. For example, this method can be overridden by any class that inherits it: Use the new modifier to explicitly hide a member inherited from a base class. To hide an inherited member, declare it in the derived class using the same name, and modify it with the new modifier.


This is all to do with polymorphism. When a virtual method is called on a reference, the actual type of the object that the reference refers to is used to decide which method implementation to use. When a method of a base class is overridden in a derived class, the version in the derived class is used, even if the calling code didn't "know" that the object was an instance of the derived class. For instance:


public class Base
{
public virtual void SomeMethod()
{
}
}

public class Derived : Base
{
public override void SomeMethod()
{
}
}

...

Base b = new Derived();
b.SomeMethod();

will end up calling Derived.SomeMethod if that overrides Base.SomeMethod.


Now, if you use the new keyword instead of override, the method in the derived class doesn't override the method in the base class, it merely hides it. In that case, code like this:


public class Base
{
public virtual void SomeOtherMethod()
{
}
}

public class Derived : Base
{
public new void SomeOtherMethod()
{
}
}

...


Base b = new Derived();
Derived d = new Derived();
b.SomeOtherMethod();
d.SomeOtherMethod();

Will first call Base.SomeOtherMethod , then Derived.SomeOtherMethod . They're effectively two entirely separate methods which happen to have the same name, rather than the derived method overriding the base method.


If you don't specify either new or overrides, the resulting output is the same as if you specified new, but you'll also get a compiler warning (as you may not be aware that you're hiding a method in the base class method, or indeed you may have wanted to override it, and merely forgot to include the keyword).


An overriding property declaration may include the sealed modifier. Use of this modifier prevents a derived class from further overriding the property. The accessors of a sealed property are also sealed.



Any method can be overridable (=virtual) or not. The decision is made by one who defines the method:


class Person
{
// this one is not overridable (not virtual)
public void GetPersonType()
{
return "person";
}

// this one is overridable (virtual)
public virtual String GetName()
{
return "generic name";
}
}

So now you can override those methods that are overridable:


class Friend : Person
{
public Friend() : this("generic name") { }

public Friend(String name)
{
this._name = name;
}

// now we override instance Person.GetName method:
public override String GetName()
{
return _name;
}
}

But you can't override GetPersonType method because it's not virtual. So now let's create two instances of those classes:


Person person = new Person();
Friend friend = new Friend("Onotole");

When non-virtual method GetPersonType is called by Fiend instance it's actually Person.GetPersonType that is called:


Console.WriteLine(friend.GetPersonType()); // "person"

When virtual method GetName is called by Friend instance it's Friend.GetName that is called.


Console.WriteLine(friend.GetName()); // "Onotole"

When virtual method GetName is called by Person instance it's Person.GetName that is called.


Console.WriteLine(person.GetName()); // "generic name"

When non-virtual method is called the method is not looked up - compiler always knows the actual method that needs to be called. With virtual methods compiler can't be sure which one to call, so it looks for it at runtime. When virtual method is called the actual method is looked up in the class hierarchy from down to up starting at the type of instance that the method is called on: for friend.GetName it looks starting at Friend class and finds it right away, for person.GetName class it starts at Person and finds it there.


Now sometimes you make a subclass, override a virtual method and you don't want any more overrides down in the hierarchy - you use sealed override for that (saying you are the last one who overrides this method):


class Mike : Friend
{
public sealed override String GetName()
{
return "Mike";
}
}

Now sometimes your friend Mike decides to change his gender and thus his name to Alice :) You could change code or subclass Mike:


class Alice : Mike
{
public new String GetName()
{
return "Alice";
}
}

Here you create a completely different method with the same name (so now you have two). So which method and when is called? It depends on how you call it:


Alice alice = new Alice();
Console.WriteLine(alice.GetName()); // the new method is called printing "Alice"
Console.WriteLine(((Mike)alice).GetName()); // the method hidden by new is called printing "Mike"

When you call it from Alice perspective you call Alice.GetName, when from Mike - you call Mike.GetName. And no lookup is made here. You can always create new methods - whether the methods you are hiding are virtual or not.


This applies to properties and events too - they generate methods underneath.



By default a method cannot be overridden in a derived class unless it is declared virtual, or abstract. virtual means check for newer implementations before calling and abstract means the same, but it is guaranteed to be overridden in all derived classes. Also, no implementation is needed in the base class because it is going to be re-defined elsewhere.


The exception to the above is the new modifier. A method not declared virtual or abstract can be re-defined with the new modifier in a derived class. When the method is called in the base class the base method executed, and when called in the derived class, the new method is executed. All the new keywords allows you to do is to have two methods with the same name in a class hierarchy.


Finally a sealed modifier breaks the chain of virtual methods and makes them not overridable again. This is not used often, but the option is there. It makes more sense with a chain of 3 classes each deriving from the previous one


A -> B -> C

if A has an virtual or abstract method, that is overridden in B, then it can also prevent C from changing it again by declaring it sealed in B.


sealed is also used in classes, and that is where you will commonly encounter this keyword.


I hope this helps.



All keywords you can find here. There are examples 2.


0 commentaires:

Enregistrer un commentaire