I couldn't understand the need or purpose of "protected" when i have "virtual/override" could someone explain me what do i need those 2 things if they are almost the same.
Edit:
Thanks for all the helpers, i now understand that "protected" is only for visibility purposes, while virtual/override is for class behavior.
They are certainly not almost the same.
The protected modifier sets the visibility of a field or method: such a member can only be accessed from the class it is defined in or from a derived class.
The virtual modifier specifies that the method it is applied to can be overridden in a derived class.
These modifiers can be combined: a method can be protected and virtual.
protected means private for current class and derived classes
virtual means it can be used as-is but also be overridden in derived classes
Maybe it is better with some code instead of things you have probably already read, here is a little sample you can play with. Try removing the comments (//) and you can see that the compiler tells you that the properties cannot be accessed
[TestFixture]
public class NewTest
{
[Test]
public void WhatGetsPrinted()
{
A a= new B();
a.Print(); //This uses B's Print method since it overrides A's
// a.ProtectedProperty is not accesible here
}
}
public class A
{
protected string ProtectedProperty { get; set; }
private string PrivateProperty { get; set; }
public virtual void Print()
{
Console.WriteLine("A");
}
}
public class B : A
{
public override void Print() // Since Print is marked virtual in the base class we can override it here
{
//base.PrivateProperty can not be accessed hhere since it is private
base.ProtectedProperty = "ProtectedProperty can be accessed here since it is protected and B:A";
Console.WriteLine("B");
}
}
I can be argued that the Most important distinction about virtual, is that this causes the compiler, when calling a method member polymorphically, which implementation to bind the compiled code to. When you call a member of a class from client code where the actual type of the object is, say derived class foo, but the variable it is being called on is actually typed (declared) as some base class, say bar, Members declared as virtual will bind to the implementation in the actual object type, (or to the most derived base class of the objects type that has an implementation). Members not declared as virtual will bind to the implementation in the type that the variable is declared to be.
A. Virtual. then, if the member is declared as virtual, the implementation in the derived class will be executed even if the variable is declared as a base type.
public class Animal
{ public virtual Move() { debug.Print("Animal.Move()"); }
public class Bird: Animal
{ public virtual override Move() { debug.Print("Bird.Move()"); }
Animal x = new Bird();
x.Move(); // Will print "Bird.Move"
B. Not Virtual. When a member which is not declared as virtual, then the implementation will be chosen based on the declared type of the variable the method is executed on. So if you have a Bird Object, in variable x declared as `Animal', and you call a method that is implemented in both classes, the compiler will bind to the implementation in the Animal class, not in Bird, even though the object is really a Bird.
public class Animal
{ public Move() { debug.Print("Animal.Move()"); }
public class Bird: Animal
{ public Move() { debug.Print("Bird.Move()"); }
Animal x = new Bird();
x.Move(); // Will print "Animal.Move"
I think you need to understand above two things properly, since both has different purpose.
protected is the type or member can only be accessed by code in the same class or struct, or in a derived class.
The virtual keyword is for modify a method, property and allow it to be overridden in a derived class.
Related
I'm new to C# , just a question on multi level inheritance
Let's say we have the following classes:
Class Employee
{
public virtual void CalculateBonus() {
...
}
}
class SalesPerson : Employee
{
public override void CalculateBonus() {
...
}
}
let's say we have another class that derives from SalesPerson
class PTSalesPerson : SalesPerson
{
public override void CalculateBonus() {
...
}
}
so my questions is simple, the virtual keyword in the base class is needed to be overridable by its child class. Apply the same logic, the virtual keyword should also applying in the SalesPerson class as:
class SalesPerson : Employee
{
public virtual override void CalculateBonus() {
... //compiler error
}
}
so that PTSalesPerson can override its parent method.
so does mean that 'virtual' keyword needs to appear only in level 1 base class? or override = override + virtual?
You cannot mark an overriden method as virtual as it is by definition already virtual
virtual (C# Reference)
Remarks
When a virtual method is invoked, the run-time type of the object is
checked for an overriding member. The overriding member in the most
derived class is called, which might be the original member, if no
derived class has overridden the member.
By default, methods are non-virtual. You cannot override a non-virtual
method.
You cannot use the virtual modifier with the static, abstract, private, or override modifiers.
If you do, you get a nasty compile time error
Compiler Error CS0113
A member 'function' marked as override cannot be marked as new or
virtual
It is mutually exclusive to mark a method with the new and override
keywords.
To answer the underlying concern, you mark the lowest level that needs to be overriden with virtual, any derived class then can override it
The VIRTUAL keyword means that ANY child-level class CAN Override the given function.
So, if NONE of the child level classes have an override declaration of the function, they will all still have that function, it would just go to the top-most employee class.
If for example, you only did an override specifically to the PTSalesPerson class, then only THAT class would have the different functionality... The Employee and SalesPerson would still operate on the "Employee" level declaration of the function/method.
Does this help clarify for you?
Once any method is declared as virtual in its parent hierarchy, any child will ALWAYS be POSSIBLE to OVERRIDE from its parent regardless of the level. But also, Lets say you have a hierarchy level
Class1
Class2 : Class1
Class3 : Class2
Class4 : Class3
and you declare an override at Class3... Class4's instance will be operating based on IT's parent which is Class3's implementation of the method call, not Class1's declaration.
Now, if you want to do a combination, you can always call the base method, then do more.
Ex:
Class Employee
{
public decimal MyBonus = 0.0m;
public virtual void CalculateBonus()
{
MyBonus = MySales * .13m;
}
}
class SalesPerson : Employee
{
}
class PTSalesPerson : SalesPerson
{
public override void CalculateBonus()
{
// go do the NORMAL Calculation at the EMPLOYEE Level
base.CalculateBonus();
// Now continue from that... As Part-Time sales person,
// they get 1/4 of that rate. So take whatever the result
// WAS and multiply by .25
MyBonus = MyBonus * .25m;
}
}
Clarification on calling chain of methods
Per your comment/question, the method that PTSalesPerson would override would be Employees because that is the next declared method up the chain... For a test, create your own classes like above and just do a MessageBox.Show("something") and see what happens on each. If SalesPerson class had a declared method, then THAT would be the one overridden, but is also the "base.CalculateBonus" that is called.
Think of the "base." as family hierarchy. You are child to your parents... Grand child to your grandparents. So your "base." would be your direct parent.
ADDITIONAL POINT on Inheritance
One caveat I did not disclose (thanks Servy) is that of advanced class declarations where a class is marked as SEALED. Sealed classes basically lock the class so no further derived classes can be done against it. And that is applicable to the entire class... properties, methods, functionality, etc.
In "The C# Programming Language" book Eric Lippert mentioned this:
A subtle point here is that an overridden virtual method is still considered to be a method of the class that introduced it, and not a method of the class that overrides it.
What is the significance of this statement? Why does it matter if the overridden virtual method is considered to be a method of the class that introduced it (or otherwise) since the overridden method will never be called unless you are dealing with the derived class?
It matters when you have a reference of one type pointing to an object of a different type.
Example:
public class BaseClass {
public virtual int SomeVirtualMethod() { return 1; }
}
public class DerivedClass : BaseClass {
public override int SomeVirtualMethod() { return 2; }
}
BaseClass ref = new DerivedClass();
int test = ref.SomeVirtualMethod(); // will be 2
Because the virtual method is a member of the base class, you can call the overriding method with a reference of the base class type. If it wasn't, you would need a reference of the derived type to call the overriding method.
When you are shadowing a method instead of overriding it, the shadowing method is a member of the derived class. Depending on the type of the reference you will be calling the original method or the shadowing method:
public class BaseClass {
public int SomeMethod() { return 1; }
}
public class DerivedClass : BaseClass {
public new int SomeMethod() { return 2; }
}
BaseClass ref = new DerivedClass();
int test = ref.SomeMethod(); // will be 1
DerivedClass ref2 = ref;
int test2 = ref2.SomeMethod(); // will be 2
Here's the full quote from the book:
A subtle point here is that an overridden virtual method is still considered to be a method of the class that introduced it, and not a method of the class that overrides it. The overload resolution rules in some cases prefer members of more derived types to those in base types; overriding a method does not "move" where that method belongs in this hierarchy.
At the very beginning of this section, we noted that C# was designed with versioning in mind. This is one of those features that helps prevent "brittle base-class syndrome" from causing versioning problems.
The full quote makes it clear that Eric Lippert is talking specifically about method overloading, not just about how virtual methods work.
As an example, consider the following program:
class Base
{
public virtual void M2(int i) { }
}
class Derived : Base
{
public void M1(int i) { Console.WriteLine("Derived.M1(int)"); }
public void M1(float f) { Console.WriteLine("Derived.M1(float)"); }
public override void M2(int i) { Console.WriteLine("Derived.M2(int)"); }
public void M2(float f) { Console.WriteLine("Derived.M2(float)"); }
public static void Main()
{
Derived d = new Derived();
d.M1(1);
d.M2(1);
}
}
I think many developers would be surprised that the output is
Derived.M1(int)
Derived.M2(float)
Why would d.M2(1) invoke Derived.M2(float) even though Derived.M2(int) is a better match?
When the compiler is determining what the M1 in d.M1(1) refers to, the compiler sees that both M1(int) and M1(float) are introduced in Derived, so both overloads are applicable candidates. The compiler selects M1(int) over M1(float) as the best match for the integer argument 1.
When the compiler is determining what the M2 in d.M2(1) refers to, the compiler sees that M2(float) is introduced in Derived and is an applicable candidate. According to the overload resolution rules, "methods in a base class are not candidates if any method in a derived class is applicable". Because M2(float) is applicable, this rule prevents M2(int) from being a candidate. Even though M2(int) is a better match for the integer argument and even though it's overridden in Derived, it's still considered to be a method of Base.
Understanding that an overridden virtual method belongs to the class which introduces it, rather than the class that overrides it, makes it easier to understand the way class members are bound. Except when using dynamic objects, all bindings in C# are resolved at compile time. If a BaseClass declares a virtual method foo, and DerivedClass:BaseClass overrides foo, code which attempts to call foo on a variable of type BaseClass will always be bound to virtual method "slot" BaseClass.foo, which will in turn point to the actual DerivedClass.foo method.
This understanding can be especially important when dealing with generics, since in C#, unlike C++, members of generic types are bound according to the generics' constraints, rather than according to the concrete generic types. For example, suppose there were a SubDerivedClass:DerivedClass which created a new virtual method foo(), and one defined a method DoFoo<T>(T param) where T:BaseClass {param.foo();}. The param.foo() call would be bound to BaseClass.foo even if the method were invoked as DoFoo<SubDrivedClass>(subDerivedInstance). If the parameter were cast to SubDerivedClass before invoking foo, the call would be bound to SubDrivedClass.foo(), but the compiler can't tell when producing DoFoo<T> that T will be anything more specific than BaseClass, it can't bind to anything that doesn't exist in BaseClass.
Incidentally, there are times it would be useful if a class could simultaneously override a base-class member and create a new one; for example, given an abstract base class ReadableFoo with some abstract read-only property, it would be helpful if a class MutableFoo could both provide an override for that property and define a read-write property with the same name. Unfortunately, .net does not allow that. Given such a restriction, the best approach may be for ReadableFoo to provide a concrete non-virtual read-only property which calls an protected abstract method with a different name to get the value. That way, a derived class could shadow the read-only property with a read-write one (that would call the same virtual method for reading, or a new (possibly virtual) method for writing.
(following is untested)
class BaseClass
{
public virtual void foo() {Console.WriteLine("BaseClass.Foo");
}
class DerivedClass:BaseClass
{
public override void foo() {Console.WriteLine("Derived.Foo");
}
class SubDerivedClass:DerivedClass
{
public new virtual void foo() {Console.WriteLine("SubDerived.Foo");
}
class MegaDerivedClass:SubDerivedClass
{
public override void foo() {Console.WriteLine("MegaDerived.Foo");
}
void DoFoo1<T>(T param) where T:BaseClass
{
param.foo();
}
void DoFoo1<T>(T param) where T:SubDerivedClass
{
param.foo();
}
void test(void)
{
var megaDerivedInstance = new MegaDerivedClass();
DoFoo1<MegaDerivedClass>(megaDerivedInstance);
DoFoo2<MegaDerivedClass>(megaDerivedInstance);
}
A SubDerivedClass has two virtual foo() methods: BaseClass.foo() and SubDerivedClass.foo(). A MegaDerivedClass has those same two methods. Note that classes derived from SubDerivedClass() which attempt to override foo will override SubDerivedClass.foo() and will not affect BaseClass.foo(); with the declarations as above, no derivative of SubDerivedClass can override BaseClass.Foo. Note also that casting an instance of SubDerivedClass or a subclass thereof to DerivedClass or BaseClass will expose the BaseClass.foo virtual method for calling.
Incidentally, if the method declaration in SubDerivedClass had been friend new virtual void foo() {Console.WriteLine("SubDerived.Foo");, it would be impossible for other classes within the same assembly to override BaseClass.foo() (since any attempt to override foo() would override SubDerivedClass.foo()), but classes outside the assembly which derive from SubDerivedClass wouldn't see SubDerivedClass.foo() and could thus override BaseClass.foo().
How do I prevent a method from being overridden in a derived class?
In Java I could do this by using the final modifier on the method I wish to prevent from being overridden.
How do I achieve the same in C#?
I am aware of using sealed but apparently I can use it only with the override keyword?
class A
{
public void methodA()
{
// Code.
}
public virtual void methodB()
{
// Code.
}
}
class B : A
{
sealed override public void methodB()
{
// Code.
}
}
So in the above example I can prevent the methodB() from being overridden by any classes deriving from class B, but how do I prevent class B from overriding the methodB() in the first place?
Update: I missed the virtual keyword in the methodB() declaration on class A when i posted this question. Corrected it.
You don't need to do anything. The virtual modifier specifies that a method can be overridden. Omitting it means that the method is 'final'.
Specifically, a method must be virtual, abstract, or override for it to be overridden.
Using the new keyword will allow the base class method to be hidden, but it will still not override it i.e. when you call A.methodB() you will get the base class version, but if you call B.methodB() you will get the new version.
As you mentioned, you can prevent further overriding of MethodB in class B by using sealed with override
class B : A
{
public sealed override void methodB()
{
Console.WriteLine("Class C cannot override this method now");
}
}
Use of the sealed modifier along with override prevents a derived class from further overriding the method.
If you do not want methodB in class A to be overridden by any child classes, do not mark that method virtual. Simply remove it. virtual keyword enable the method to be overridden in child classes
public void methodA()
{
}
Use sealed keyword on your classes to prevent further overriding of the class
In C#, a function not marked virtual (which also includes overrides of virtual functions) is effectively sealed and cannot be overridden. So, your example code actually won't compile because the override keyword is not valid unless there is a method marked virtual with the same signature in a base class.
If A.methodB() were marked virtual, then you could override the method from A, but prevent it being further overridden in classes deriving more indirectly, using the sealed keyword exactly as you have shown.
One thing to keep in mind is that while method overriding can be prevented, method hiding cannot. Given your current definition of class A, the following definition of class B is legal and there's nothing you can do about it:
class B:A
{
public new void methodB()
{
//code
}
}
The new keyword basically "breaks" the inheritance/overriding hierarchy as it pertains to this one method; any reference to a class B, treated as a class B (or any further derived type) will use the implementation from class B and ignore the one from class A unless B's implementation specifically calls back to it. However, if you were to treat an instance of class B as a class A (by casting it or passing it as a parameter), then the "new" implementation is ignored.
This differs from overriding, where a class B that is being treated as a class A and truly overrides a virtual methodB would still use class B's override of the method. Also understand that method hiding is inferred (though you will get a compiler warning); if you declare a method with the same signature in a derived class and do not specify either new or override, the base class method will be hidden.
In a base class, the sealed keyword is only used to prevent a class from being derived, but in inherited classes it can be used to prevent another inherited class from overriding the method.
To prevent a base class method from being overridden, just do not specify it as virtual. In the example you provided, class B could not override methodB because methodB was not marked as virtual on the original class.
this will compile:
class A
{
public virtual void methodA()
{
//code
}
public virtual void methodB()
{
//code
}
}
class B:A
{
public override void methodB()
{
//code
}
}
this will not:
class A
{
public void methodA()
{
//code
}
public void methodB()
{
//code
}
}
class B:A
{
public override void methodB()
{
//code
}
}
EDITTED: clarified and corrected my original statement about the sealed keyword
I thought I had this nailed, and then I go and look at some source at work and am left wondering why there are so many contradictions in what I read from msdn and what I am seeing in source....
My understanding is that the virtual keyword can be used in method declarations to allow any deriving classes to override it.
The override keyword would then need to be used in the derived class when implementing the superclass' virtual method....
For example:
public abstract class A
{
public virtual string GetName();
}
public class B:A
{
//assume there are some defined properties.
public override string GetName()
{
return FirstName;
}
}
I have a few questions:
1) Is it really necessary to define a method as virtual if it has no implementation? Surely it can just be overwritten in the subclass without the use of virtual and override?
2) If (1) is incorrect, am I right in thinking that every virtual method must be overridden in the subclass using it....
EDIT:
You're right my code will not compile... I want to know why....I uinderstand your answers but then I saw this:
public abstract class RequestHandler<TRequest, TResponse> : RequestHandler, IRequestHandler<TRequest>, IRequestHandler, IDisposable, ITypedRequestHandler
where TRequest : global::Agatha.Common.Request
where TResponse : global::Agatha.Common.Response, new()
{
protected RequestHandler();
public virtual void AfterHandle(TRequest request);
public virtual void BeforeHandle(TRequest request);
public override Response CreateDefaultResponse();
public TResponse CreateTypedResponse();
public override Response Handle(Request request);
public abstract Response Handle(TRequest request);
}
The above doesnt cause the compiler to complain...
Firstly the above code is invalid. A virtual method still has to have a body with a default implementation. to do what you have done above you would need to use the abstract keyaord instead of virtual.
abstract means that there is no method body provided but that any class deriving from it must implement this method (unless it is abstract too).
I think this pretty much answers your questions....
If it has no implementation then it cannot be virtual, it must be abstract. If it has an implementation that just does nothing then that must be implemented.
The whole point of a virtual class is that it has default behaviour so you can choose whether or not to override it. If it were abstract then you would have to override it (unless you were deriving another abstract class).
Is it really necessary to define a method as virtual if it has no implementation?
You can make the method abstract (it will implicitly make it virtual).
Surely it can just be overwritten in the subclass without the use of virtual and override?
If you just "overwrite" it without explicitly overriding it, it won't be the same method, and calling the method on a variable of the base class won't call the derived method (it won't participate in polymorphism). You would just be "hiding" the method of the base class (the compiler actually warns you about this, if it's really what you want to do you must use the new modifier.)
An example will make it clearer:
class B
{
public virtual void M() { Console.WriteLine("B.M") };
}
class D1 : Base
{
// Hides the base method
public new void M() { Console.WriteLine("D1.M") };
}
class D2 : Base
{
// Overrides the base method
public override void M() { Console.WriteLine("D2.M") };
}
...
D1 d1 = new D1();
d1.M(); // Prints "D1.M"
B b1 = d1;
b1.M(); // Prints "B.M", because D1.M doesn't override B.M
D2 d2 = new D1();
d2.M(); // Prints "D2.M"
B b2 = d2;
b2.M(); // Also prints "D2.M", because D2.M overrides B.M
If (1) is incorrect, am I right in thinking that every virtual method must be overridden in the subclass using it....
No, only if it's abstract... a virtual method can have an implementation, and in that case derived classes are not forced to override it.
1) Is it really necessary to define a method as virtual if it has no implementation? Surely it can just be overwritten in the subclass without the use of virtual and override?
As said in other answers, virtual methods need to have implementations. You are confusing it with abstract.
If you were asking whether virtual methods which do have an implementation need to be declared virtual: In C#, yes, it is necessary. In Java, you can override any old method. It was a C# design decision to require overriding to be specifically allowed with the virtual keyword, so that methods cannot be overridden unless intended by the programmer.
If the programmer has not expressed intent by not using virtual, you can still "override" methods, with the new keyword. However, this works a bit differently. Hopefully this code will help illustrate the concept:
class Program
{
static void Main(string[] args)
{
var baseC = new BaseClass();
var extC = new ExtClass();
var lazyC = new LazyClass();
Console.WriteLine(baseC.NewMethod());
Console.WriteLine(baseC.VirtualOverrideMethod());
Console.WriteLine("---");
Console.WriteLine(extC.NewMethod());
Console.WriteLine(extC.VirtualOverrideMethod());
Console.WriteLine("---");
Console.WriteLine(((BaseClass) extC).NewMethod());
Console.WriteLine(((BaseClass) extC).VirtualOverrideMethod()); // Redundant typecast
Console.WriteLine("---");
Console.WriteLine(lazyC.VirtualOverrideMethod());
Console.ReadKey();
}
public class BaseClass
{
public BaseClass()
{
}
public string NewMethod()
{
return "NewMethod of BaseClass";
}
public virtual string VirtualOverrideMethod()
{
return "VirtualOverrideMethod of BaseClass";
}
}
class ExtClass : BaseClass
{
public new string NewMethod()
{
return "NewMethod of ExtClass";
}
public override string VirtualOverrideMethod()
{
return "VirtualOverrideMethod of ExtClass";
}
}
class LazyClass : BaseClass
{
}
}
Output:
NewMethod of BaseClass
VirtualOverrideMethod of BaseClass
---
NewMethod of ExtClass
VirtualOverrideMethod of ExtClass
---
NewMethod of BaseClass
VirtualOverrideMethod of ExtClass
---
VirtualOverrideMethod of BaseClass
2) If (1) is incorrect, am I right in thinking that every virtual method must be overridden in the subclass using it....
Not at all. virtual is a way of saying, "it's okay if you want to override this method". In fact, I included LazyClass in my code above to show this.
The above doesnt cause the compiler to complain...
I haven't used interfaces much, but that looks like one. In my code, if I change
class ExtClass : BaseClass
{
public new string NewMethod()
{
return "NewMethod of ExtClass";
}
public override string VirtualOverrideMethod()
{
return "VirtualOverrideMethod of ExtClass";
}
}
to:
class ExtClass : BaseClass
{
public new string NewMethod()
{
return "NewMethod of ExtClass";
}
public override string VirtualOverrideMethod()
{
return "VirtualOverrideMethod of ExtClass";
}
}
I get:
error CS0501: 'OverrideTest.Program.ExtClass.VirtualOverrideMethod()' must declare a body because it is not marked abstract, extern, or partial
From Visual Studio 2010. The same goes for the virtual method of my BaseClass.
The need for virtual is dictated by polymorphism. Think about what happens when you redefine a method in a subclass using new:
class Parent
{
void Foo() { Console.WriteLine("Parent"); }
virtual void Bar { Console.WriteLine("Parent"); }
}
class Child : Parent
{
new void Foo() { Console.WriteLine("Child"); } // another method Foo
override void Bar { Console.WriteLine("Child"); }
}
var child = new Child(); // a Child instance
var parent = (Parent)child; // same object, but statically typed as Parent
c.Bar(); // prints "Child"
p.Bar(); // again, prints "Child" -- expected virtual behavior
c.Foo(); // prints "Child"
p.Foo(); // but this prints "Parent"!!
For this reason, classes that are intended to be derived from (i.e. not sealed) should always mark the methods that can be overridden as virtual -- otherwise there will be confusing runtime behavior like above. There's no difference if the parent implementation actually does anything or not; the point is that it behaves differently.
ok, by declaring the method as virtual (and not wishing to override the method in the subclass), you'd be entering the world of method hiding if you were to introduce a method with the same name into the subclass. You have to define it as thus:
public abstract class A
{
public virtual string GetName()
{
return null;
}
}
public class B : A
{
//assume there are some defined properties.
public new string GetName()
{
return FirstName;
}
}
I'd recommend that you think of the abstract override approach:
public abstract class A
{
public abstract string GetName()
}
// to override
public class B : A
{
//assume there are some defined properties.
public override string GetName()
{
return FirstName;
}
}
this would be quite different. I would strongly recommend that you just override the abstract method in the subclass.
However, here's a quick ref on the subject (old but a good read):
http://www.akadia.com/services/dotnet_polymorphism.html
1) Is it really necessary to define a method as virtual if it has no
implementation? Surely it can just be overwritten in the subclass
without the use of virtual and override?
You can use an abstract methods, that have no body, but they if you derive from that class you must to override that method. All abstact methods have to be overriden in child class.
2) If (1) is incorrect, am I right in thinking that every virtual
method must be overridden in the subclass using it....
No, instead, you can use a virtual keyword to have an implementation inside that, but do not making override in a child class mandatory. Gives you more flexibility, from that point of view.
Usauly they use abstract to create rigid constrains for childs, so every child derived from it must implement specified member of base class.
That's exactly the difference between a virtual and an abstract method:
A virtual method can be overridden by derived classes if the choose to. A virtual method may or may not have a default implementation for inheritors to call into, which is done using the base keyword.
An abstract method must be overridden by derived classes. Its constraints are:
It can only be defined in an abstract class.
It cannot have an implementation, since it's up to the inheritors to define its behavior.
I'm pretty confused between some concepts of OOP: virtual, override, new and sealed override. Can anyone explain the differences?
I am pretty clear that if the derived class method is to be used, one can use the override keyword so that the base class method will be overriden by derived class. But I'm not sure about new, and sealed override.
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 d = new Derived();
d.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 the one who defines the method:
class Person
{
// this one is not overridable (not virtual)
public String GetPersonType()
{
return "person";
}
// this one is overridable (virtual)
public virtual String GetName()
{
return "generic name";
}
}
Now you can override those methods that are overridable:
class Friend : Person
{
public Friend() : this("generic name") { }
public Friend(String name)
{
this._name = name;
}
// override Person.GetName:
public override String GetName()
{
return _name;
}
}
But you can't override the GetPersonType method because it's not virtual.
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 Friend 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 body is not looked up - compiler already knows the actual method that needs to be called. Whereas with virtual methods compiler can't be sure which one to call, and it is looked up at runtime 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.
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 the method):
class Mike : Friend
{
public sealed override String GetName()
{
return "Mike";
}
}
But sometimes your friend Mike decides to change his gender and thus his name to Alice :) You could either change original code or instead subclass Mike:
class Alice : Mike
{
public new String GetName()
{
return "Alice";
}
}
Here you create a completely different method with the same name (now you have two). 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's perspective you call Alice.GetName, when from Mike's - you call Mike.GetName. No runtime lookup is made here - as both methods are non-virtual.
You can always create new methods - whether the methods you are hiding are virtual or not.
This applies to properties and events too - they are represented as 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.
public class Base
{
public virtual void SomeMethod()
{
Console.WriteLine("B");
}
}
public class Derived : Base
{
//Same method is written 3 times with different keywords to explain different behaviors.
//This one is Simple method
public void SomeMethod()
{
Console.WriteLine("D");
}
//This method has 'new' keyword
public new void SomeMethod()
{
Console.WriteLine("D");
}
//This method has 'override' keyword
public override void SomeMethod()
{
Console.WriteLine("D");
}
}
Now First thing First
Base b=new Base();
Derived d=new Derived();
b.SomeMethod(); //will always write B
d.SomeMethod(); //will always write D
Now the keywords are all about Polymorphism
Base b = new Derived();
Using virtual in base class and override in Derived will give D(Polymorphism).
Using override without virtual in Base will give error.
Similarly writing a method (no override) with virtual will write 'B' with warning (because no polymorphism is done).
To hide such warning as in above point write new before that simple method in Derived.
new keyword is another story, it simply hides the warning that tells that the property with same name is there in base class.
virtual or new both are same except
new modifier
new and override cannot be used before same method or property.
sealed before any class or method lock it to be used in Derived class and it gives a compile time error.