Virtual Functions - new override and abstract

advertisement
Virtual Functions - new and override
New and Override Methods
a.cs
class zzz
{
public static void Main()
{
yyy a = new yyy();
xxx b = new xxx();
yyy c = new xxx();
a.abc(); a.pqr(); a.xyz();
b.abc(); b.pqr(); b.xyz();
c.abc(); c.pqr(); c.xyz();
}
}
class yyy
{
public void abc()
{
System.Console.WriteLine(“yyy abc”);
}
public void pqr()
{
System.Console.WriteLine(“yyy pqr”);
}
public void xyz()
{
System.Console.WriteLine(“yyy xyz”);
}
}
class xxx : yyy
{
public void abc()
{
System.Console.WriteLine(“xxx abc”);
}
public void pqr()
{
System.Console.WriteLine(“xxx pqr”);
}
public void xyz()
{
System.Console.WriteLine(“xxx xyz”);
}
}
Output
yyy abc
yyy pqr
yyy xyz
xxx abc
xxx pqr
xxx xyz
yyy abc
yyy pqr
yyy xyz
Compiler Warning
a.cs(30,13): warning CS0108: The keyword new is required on 'xxx.abc()' because it hides
inherited member 'yyy.abc()'
a.cs(34,13): warning CS0108: The keyword new is required on 'xxx.pqr()' because it hides
inherited member 'yyy.pqr()'
a.cs(38,13): warning CS0108: The keyword new is required on 'xxx.xyz()' because it hides
inherited member 'yyy.xyz()'
Class xxx derives from class yyy. That makes xxx the derived class and yyy the base class. The
class xxx comprises yyy and more. Thus can we not conclude, albeit in broken English that an
object that looks like xxx is bigger than one that looks like yyy. In C#, you can equate a smaller
object to a bigger object as stated earlier.
Lets take the case of object a. It looks like yyy and initialized by creating an object that also
looks like yyy. When we call the functions abc and pqr and xyz through the object a obviously it
will call them from yyy.
Object b looks like xxx, the derived class. It is initialized to an object that looks like xxx. When
we call abc, pqr and xyz through b, it calls abc, pqr and xyz from xxx.
Object c again looks like yyy but it is now initialized to an object that looks like xxx which does
not give an error as explained earlier. However there is no change at all in the output and the
behavior is same to that of object a. Hence initializing it to an object that looks like yyy or xxx
does not seem to matter.
a.cs
class zzz
{
public static void Main()
{
yyy a = new yyy();
xxx b = new xxx();
yyy c = new xxx();
a.abc(); a.pqr(); a.xyz();
b.abc(); b.pqr(); b.xyz();
c.abc(); c.pqr(); c.xyz();
}
}
class yyy
{
public void abc()
{
System.Console.WriteLine(“yyy abc”);
}
public void pqr()
{
System.Console.WriteLine(“yyy pqr”);
}
public void xyz()
{
System.Console.WriteLine(“yyy xyz”);
}
}
Compile error
a.cs(30,22): error CS0506: ‘xxx.abc()’ :
cannot override inherited member
‘yyy.abc()’ because it is not marked virtual,
abstract, or override
class xxx : yyy
{
public override void abc()
{
System.Console.WriteLine(“xxx abc”);
}
public new void pqr()
{
System.Console.WriteLine(“xxx pqr”);
}
public void xyz()
{
System.Console.WriteLine(“xxx xyz”);
}
}
We get an error because we have added two new modifiers, new and override to the functions.
The error says to add the modifier virtual to the functions in the base class.
a.cs
class zzz
{
public static void Main()
{
yyy a = new yyy();
xxx b = new xxx();
yyy c = new xxx();
a.abc(); a.pqr(); a.xyz();
b.abc(); b.pqr(); b.xyz();
c.abc(); c.pqr(); c.xyz();
}
}
class yyy
{
public virtual void abc()
{
System.Console.WriteLine(“yyy abc”);
}
public virtual void pqr()
{
System.Console.WriteLine(“yyy pqr”);
}
public virtual void xyz()
{
System.Console.WriteLine(“yyy xyz”);
}
}
class xxx : yyy
{
public override void abc()
{
System.Console.WriteLine(“xxx abc”);
}
public new void pqr()
{
System.Console.WriteLine(“xxx pqr”);
}
public void xyz()
{
System.Console.WriteLine(“xxx xyz”);
}
}
Output
yyy abc
yyy pqr
yyy xyz
xxx abc
xxx pqr
xxx xyz
xxx abc
yyy pqr
yyy xyz
There is a single subtle change in the workings of the objects c only and not a and b. Adding the
virtual modifier has made all the difference. The difference is in the object c. c looks like the
base class yyy but is initialized to an object that looks like the derived class xxx. C# remembers
this fact. When we execute c.abc(), C# remembers that object c was initialized by a xxx object
and hence it first goes to class xxx. Here the function has a modifier override which in English
means, forget about the data type of c which is yyy, call abc from xxx as it overrides the abc of
the base class. The override modifier is needed as the derived class functions will get first
priority and be called. We mean to override the abc of the base class. We are telling C# that this
abc is similar to the abc of the base class.
New has the exactly the opposite meaning. The function pqr has the new modifier. C.pqr() calls
pqr from yyy and not xxx. New means that the function pqr is a new function and it has
absolutely nothing to do with the pqr in the base class. It may have the same name pqr as in the
base class, but that is only a coincidence. As c looks like yyy, the pqr of yyy gets called even
though there is a pqr in xxx. When we do not write any modifier, then it is assumed that we
wrote new. Thus every time we write a function, C# assumes it has nothing to do with the base
class. These modifiers can only be used if the function in the base class is a virtual function. To
us virtual means that the base class is granting us permission to call the function from the
derived class and not the base class. We have however one caveat, we have to add the modifier
override if our derived class function has to be called.
a.cs
class zzz
{
public static void Main()
{
yyy a = new xxx();
yyy b = new vvv();
xxx c = new vvv();
a.abc(); a.pqr(); a.xyz();
b.abc(); b.pqr(); b.xyz();
c.abc(); c.pqr(); c.xyz();
}
}
class yyy
{
public void abc()
{
System.Console.WriteLine(“yyy abc”);
}
public virtual void pqr()
{
System.Console.WriteLine(“yyy pqr”);
}
public virtual void xyz()
{
System.Console.WriteLine(“yyy xyz”);
}
}
class vvv : xxx
{
public override void abc()
{
System.Console.WriteLine(“vvv abc”);
}
public void xyz()
{
System.Console.WriteLine(“vvv xyz”);
}
}
class xxx : yyy
{
public virtual void abc()
{
System.Console.WriteLine(“xxx abc”);
}
public new void pqr()
{
System.Console.WriteLine(“xxx pqr”);
}
public override void xyz()
{
System.Console.WriteLine(“xxx xyz”);
}
}
Output
yyy abc
yyy pqr
xxx xyz
yyy abc
yyy pqr
xxx xyz
vvv abc
xxx pqr
xxx xyz
Pretty long example. To reiterate, we are allowed to initialize a base object to a derived object.
The other way around will generate an error. This leads to an object of a base class being
initialized to an object of the derived class. The question that now springs to mind is, which
function will get called. The one from the base class or the derived class. If the base class object
declared the function virtual and the derived class used the modifier override, the derived class
function will get called. Otherwise the base class function will get executed. Thus for virtual
functions, the data type created is decided at run time. All functions not tagged with virtual are
non virtual, and the function to be called is decided at compile time, depending upon the static
data type of the object. If the object is initialized to the same data type, none of the above
apply. Whenever we have a mismatch, we need rules to resolve the mismatch. Thus we can
land up with a situation where an object to a base class can call a function in the derived class.
The object a looks like yyy but is initialized to the derived class xxx. a.abc(), first looks into the
class yyy. Here it checks whether the function abc is virtual. The answer is an emphatic no and
hence everything stops and the function abc gets called from class yyy. a.pqr does the same
thing, but the function now is virtual in class yyy. Thus C# looks at the class yyy, the one it was
initialized to. Here pqr is flagged with the modifier new. This means that pqr is a new function
which has nothing to do with the one in the base class. They only accidentally share the same
name. Thus as there is no function called pqr (as it is a new pqr) in the derived class, the one
from base class gets called. In the case of a.xyz(), the same steps are followed again, but in the
class yyy, we meet the modifier override, which overrides the function in the base class. We are
telling C# to call this function in class xxx and not the one in the base class yyy.
The object b which also looks like class yyy, is now initialized with an object that looks like vvv
and not xxx like before. As abc is non virtual it gets called from yyy. In the case of function pqr,
C# now looks into class vvv. Here it sees no function pqr and hence now looks into class xxx.
Thus the above rules repeat and it gets called from class yyy. In the case of b.xyz, in class vvv, it
is marked new by default and hence this function has nothing to do with the one in class yyy.
Hence the one from vvv does not get called but the one from class yyy where it specifies
override.
public override void xyz()
{
System.Console.WriteLine(“vvv xyz”);
}
If we change xyz in class vvv to the above, i.e. we change new to override, the xyz of vvv will get
called.
The last object c looks like xxx but is now initialized to an object that looks like the derived class
vvv. c.abc(), first looks into class xxx where it is marked as virtual. Remember abc is non virtual
in class yyy but virtual in xxx. From now on, the function abc is virtual in vvv also but not in class
yyy. Virtual is like water, it flows downwards not upwards. As abc is virtual, we now look into
class vvv. Here it is marked override and hence abc gets called from class vvv. In the case of pqr,
pqr is marked virtual in class yyy and new in xxx, but as there is no function pqr in vvv, none of
the modifiers matter at all. Thus it gets called from class xxx. Lastly for function xyz, in class vvv
it is marked new. Hence it has no connection with the xyz in class xxx and thus function xyz gets
called from xxx and not yyy.
a.cs
class zzz
{
public static void Main()
{
yyy a = new vvv();
a.pqr();
xxx b = new vvv();
b.pqr();
}
}
class yyy
{
public virtual void pqr()
{
System.Console.WriteLine(“yyy pqr”);
}
}
class xxx : yyy
{
public new void pqr()
{
System.Console.WriteLine(“xxx pqr”);
}
}
class vvv : xxx
{
public override void pqr()
{
System.Console.WriteLine(“vvv pqr”);
}
}
This method is
virtual
Then this method should be override or
virtual
Note: If the derived class is derived with the
another derived class then only we can use
virtual method
If the function of the derived class has an
override modifier then function of the base
class should have virtual modifier.
Note: If the base class is derived with some
other class which has virtual function then the
function can be override also
Compiler Error
a.cs(17,22): error CS0506: ‘vvv.pqr()’ : cannot override inherited member ‘xxx.pqr()’ because it
is not marked virtual, abstract, or override
We get an error as the function pqr in class xxx is marked new. This means that it hides the
pqr of class yyy. Form the viewpoint of class vvv, xxx does not supply a function called pqr. The
pqr in class xxx has nothing to do with the pqr in yyy. This means that the function pqr of xxx
does not inherit the virtual modifier from the function pqr of class yyy. This is what the
compiler is complaining about. As the function pqr in xxx has no virtual modifier, in vvv we
cannot use the modifier override. You can, however, use the modifier new and remove the
warning.
a.cs
class zzz
{
public static void Main()
{
yyy a = new vvv();
a.pqr();
xxx b = new vvv();
b.pqr();
}
}
class yyy
{
public virtual void pqr()
{
System.Console.WriteLine(“yyy pqr”);
}
}
class xxx : yyy
{
public virtual new void pqr()
{
System.Console.WriteLine(“xxx pqr”);
}
}
class vvv : xxx
{
public override void pqr()
{
System.Console.WriteLine(“vvv pqr”);
}
}
Output
yyy pqr
vvv pqr
and if we remove the override modifier from pqr in vvv we get
public void pqr()
{
System.Console.WriteLine(“vvv pqr”);
}
Output
yyy pqr
xxx pqr
That’s the problem with virtual functions. We call them the cause of migraine. The answers are
always different from what you expect. Object a looks like a yyy but is initialized to the derived
class vvv. As pqr is virtual, C# now looks into class vvv. However before looking into the class, it
realizes that in class xxx, pqr is new. This cuts of all connection with the pqr in yyy. Thus the
word new is preceded with virtual, otherwise the override modifier would give us an error in
class vvv. As pqr in class xxx is new function, having nothing to do with the class yyy, class vvv
inherits a new which also has nothing to do with the class yyy. The pqr in class vvv is related to
the pqr of class xxx and not of class yyy. Thus the pqr of class yyy gets called.
In the second case object b looks like class xxx now but is initialized to an object of class vvv. C#
first looks at class xxx. Here pqr is new and virtual, which makes it a unique function pqr.
Unfortunately, the pqr in vvv has the override modifier which sees to it that the pqr of vvv hides
the pqr of xxx. This calls the pqr of vvv instead. If we remove the override modifier from pqr in
class vvv, the default is new, that cuts off the umbilical cord from the pqr of xxx. Thus, as it is, a
new function, the pqr of xxx gets called.
A virtual function cannot be marked by the modifiers static, abstract or override. A non virtual
function is said to be invariant. This means that the same function gets called always,
irrespective of whether one exists in the base class or derived class. In a virtual function the
run-time type of the instance decides on which function to be called and not the compile-time
type as is in the case of non virtual functions. For a virtual function there exists a most derived
implementation which gets always gets called.
a.cs
class zzz
{
public static void Main()
{
yyy a = new vvv();
xxx b = new vvv();
www c = new vvv();
vvv d = new vvv();
a.pqr(); b.pqr(); c.pqr(); d.pqr();
}
}
class yyy
{
public virtual void pqr()
{
System.Console.WriteLine(“yyy pqr”);
}
}
class xxx : yyy
{
public override void pqr()
{
System.Console.WriteLine(“xxx pqr”);
}
}
class www : xxx
{
public virtual new void pqr()
{
System.Console.WriteLine(“www pqr”);
}
}
class vvv : www
{
public override void pqr()
{
System.Console.WriteLine(“vvv pqr”);
}
}
Output
xxx pqr
xxx pqr
vvv pqr
vvv pqr
One last explanation of virtual with a slightly more complex example involving 4 classes.
The first line in Output, xxx pqr, is the result of the statement a.pqr();. We have the function pqr
as virtual in class yyy. Hence, when using new, we now proceed to class xxx and not vvv as
explained earlier. Here, pqr has an override and C# knows that class www inherits this function
pqr. In class www, as it is marked as new, C# will now backtrack and not proceed further to
class vvv. Hence the function pqr gets called from class xxx as shown in the output.
public override void pqr()
{
System.Console.WriteLine(“www pqr”);
}
If we change the function pqr in class www to override, then C# will proceed to class vvv and
call the pqr of class vvv as it overrides the pqr of www. Remove the override from pqr in class
vvv and the function will get called from class www as the default is new.
For object b, everything remains the same as object a, because it overrides the pqr of class yyy.
Restoring back the defaults, lets look at the third line. Object c looks like www. In class www,
pqr is a new and hence it has nothing to do with the earlier pqr functions. In class vvv, we are
overriding the pqr of class www and hence the pqr of vvv gets called. Remove the override and
then it will get called from class www. The object d thankfully follows none of the above rules
as the left and the right of the equal to sign are the same data types.
An override method is a method that has the override modifier included on it. This introduces a
new implementation of a method. You cannot use the modifiers new, static or virtual along
with override. However abstract is permitted.
a.cs
class zzz
{
public static void Main()
{
yyy a = new xxx();
a.pqr();
yyy b = new www();
b.pqr();
}
}
class yyy
{
public virtual void pqr()
{
System.Console.WriteLine(“yyy pqr”);
}
}
class xxx : yyy
{
public override void pqr()
{
base.pqr();
System.Console.WriteLine(“xxx pqr”);
}
}
class www : xxx
{
public override void pqr()
{
base.pqr();
System.Console.WriteLine(“www pqr”);
}
}
Output
yyy pqr
xxx pqr
yyy pqr
xxx pqr
www pqr
Using the keyword base, we can access the base class functions. Here whether pqr is virtual or
not, it is treated as non virtual by the keyword base. Thus the base class pqr will always be
called. The object a knows that pqr is virtual. When it goes to yyy, it sees base.abc and hence it
calls the pqr of yyy. In the second case, it first goes to class vvv, here it calls the base.abc, i.e.
the function pqr of class xxx, which in turn calls function pqr in class yyy.
a.cs
class zzz
{
public static void Main()
{
yyy a = new xxx();
a.pqr();
}
}
class yyy
{
public virtual void pqr()
{
System.Console.WriteLine(“yyy pqr”);
}
}
class xxx : yyy
{
public override void pqr()
{
((yyy)this).pqr();
System.Console.WriteLine(“xxx pqr”);
}
}
Output
Unhandled Exception: StackOverflowException.
No amount of casting will stop the infinite loop. Thus even though this is being cast to a yyy, it
will always call pqr from xxx and not yyy. Hence you see no output.
a.cs
class zzz
{
public static void Main()
{
yyy a = new www();
xxx b = new www();
a.pqr(); a.xyz();
b.pqr(); b.xyz();
}
}
class yyy
{
public virtual void pqr()
{
System.Console.WriteLine(“yyy pqr”);
}
public virtual void xyz()
{
System.Console.WriteLine(“yyy xyz”);
}
}
class xxx : yyy
{
private new void pqr()
{
System.Console.WriteLine(“xxx pqr”);
}
public new void xyz()
{
System.Console.WriteLine(“xxx xyz”);
}
}
class www : xxx
{
public override void pqr()
{
System.Console.WriteLine(“www pqr”);
}
public void xyz()
{
System.Console.WriteLine(“www xyz”);
}
}
Output
www pqr
yyy xyz
www pqr
xxx xyz
More virtual functions, more complications in life. Let us embark on a thousand mile journey
with a single step.
When we have a statement a.pqr, C# starts at the class yyy as usual, sees virtual, then goes to
class xxx. Here pqr is private and hence its scope is limited to class xxx. The modifier new is thus
ignored. C# now goes to class www where the pqr overrides the pqr of class yyy and thus we
see www pqr. If we remove the override modifier from function pqr in class www, as it is a new
function, it will now be called from class yyy. a.xyz calls pqr from yyy due to the explanation
given many times before i.e. they are all news.
b.pqr knows that pqr in class xxx is private. The scope of this pqr does not extend to class www,
the derived class. As the pqr in class www overrides the pqr of class xxx, the one from class
www gets called as it overrides the one from the base class yyy. If you change the override to
new, then the pqr in www is a new one and has nothing to do with the one from yyy. This calls
pqr from the base class yyy.
b.xyz calls it from class xxx. This has already been explained at least a trillion times earlier.
Abstract Classes
a.cs
public class zzz
{
public static void Main()
{
new aaa();
}
}
abstract class aaa
{
}
Compiler Error
a.cs(5,1): error CS0144: Cannot create an instance of the abstract class or interface ‘aaa’
The keyword abstract can be written before a class. It is called a class modifier. An abstract
class cannot be instantiated by the keyword new. We cannot create an object that looks like
aaa (abstract class name). Thus we cannot use the class and for all practical purposes the class
is useless to us.
a.cs
public class zzz
{
public static void Main()
{
new aaa();
}
}
abstract class aaa
{
public int i;
public void abc()
{
}
}
The error remains the same. Since we have used the modifier abstract in front of the class we
cannot use new. Had we removed the modifier abstract, all would be fine. This program is to
show that an abstract class can contain variables and functions.
a.cs
public class zzz
{
public static void Main()
{
new bbb();
}
}
abstract class aaa
{
public int i;
public void abc()
{
}
}
The Abstract class can be derived with the
derived class and used it by instantiating
the derived class.
class bbb : aaa
{
}
We can derive a class bbb from an abstract class aaa. Thus creating an object that looks like bbb
does not give us any error. We cannot yet use aaa directly.
a.cs
public class zzz
{
public static void Main()
{
new bbb();
}
}
abstract class aaa
{
public void pqr();
public int i;
public void abc()
{
}
}
Compiler Error
a.cs(10,13): error CS0501: ‘aaa.pqr()’
must declare a body because it is not
marked abstract or extern or partial
class bbb : aaa
{
}
In an abstract class we have added a function prototype. An extern or abstract function
implies that the actual definition or code is created somewhere else. A function prototype in an
abstract class must also be declared abstract as per the rules of C#.
a.cs
public class zzz
{
public static void Main()
{
new bbb();
}
}
abstract class aaa
{
abstract public void pqr();
public int i;
public void abc()
{
}
}
class bbb : aaa
{
}
Compiler Error
a.cs(16,7): error CS0534: ‘bbb’ does not implement inherited abstract member ‘aaa.pqr()’
After declaring pqr abstract in aaa, we get another error. We are not allowed to create objects
that look like bbb because it is derived from aaa, an abstract class which has one abstract
function. We have to implement this abstract function pqr in bbb .
a.cs
public class zzz
{
public static void Main()
{
new bbb();
}
}
abstract class aaa
{
abstract public void pqr();
public int i;
public void abc()
{
}
}
class bbb : aaa
{
public void pqr()
{
}
}
Compiler Warning
a.cs(18,13): warning CS0114: ‘bbb.pqr()’ hides inherited member ‘aaa.pqr()’. To make the
current method override that implementation, add the override keyword. Otherwise add the
new keyword.
Compiler Error
a.cs(16,7): error CS0534: ‘bbb’ does not implement inherited abstract member ‘aaa.pqr()’
Now we are really lost. The error clearly says that both classes aaa and bbb have a similar
function called pqr. Whenever a class (bbb) derives from another class (aaa) and they both
have a function with the same name, an error results. The only way out is for the derived class
bbb to explicitly add a keyword override to the function definition. This tells the compiler that
we know that the base class has a function of the same name and we want the pqr of bbb to be
called, not aaa’s . It is more of a caution exercised by the compiler so that you do not
inadvertently override functions of the base class. C# has a large number of such cautions that
make you think.
a.cs
public class zzz
{
public static void Main()
{
new bbb();
}
}
abstract class aaa
{
abstract public void pqr();
public int i;
public void abc()
{
}
}
Abstract function should not have a
body like open and close brackets and
content such as functions or variables.
class bbb : aaa
{
public override void pqr()
{
}
}
The warning vanishes after using the keyword override.
a.cs
public class zzz
{
public static void Main()
{
new bbb();
}
}
abstract class aaa
{
abstract public void pqr();
public int i;
public void abc()
{
}
}
class bbb : aaa
{
public override int pqr()
{
}
}
Compiler Error
a.cs(18,21): error CS0508: ‘bbb.pqr()’: cannot change return type when overriding inherited
member ‘aaa.pqr()’
When you are overriding an abstract function from a derived class, you cannot change the
parameters passed to it or the return type. If the abstract class has 5 functions, the class
derived from it should also implement the same 5 functions without changing return type
and/or parameters passed to it.
a.cs
public class zzz
{
public static void Main()
{
new bbb();
}
}
abstract class aaa
{
abstract public void pqr();
abstract public void pqr1();
abstract public void pqr2();
public int i;
public void abc()
{
}
}
class bbb : aaa
{
public override void pqr()
{
}
}
Compiler Error
a.cs(18,7): error CS0534: ‘bbb’ does not implement inherited abstract member ‘aaa.pqr1()’
a.cs(18,7): error CS0534: ‘bbb’ does not implement inherited abstract member ‘aaa.pqr2()’
The error goes away if we implement functions pqr1 and pqr2 in bbb.
An abstract class implies that the class is incomplete and cannot be directly used. It can only be
used as a base class for other classes to derive from. Hence we get a error if we use new on an
abstract class. If we do not initialize(don’t set a value) a variable in an abstract class, it will have
a value of 0 which is what the compiler kept warning us about. We can initialize i to any value
we want. The variables have the same use and meaning in an abstract class like any other class.
Whenever a class is incomplete i.e. we do not have the code for certain functions, we make
those functions abstract and the class abstract . This enables us to compile the class without
errors. Other classes can then derive from our incomplete class but they have to implement the
abstract i.e. our incomplete functions. Abstract thus enables us to write code for part of the
class and allows the others to complete the rest of the code.
a.cs
public class zzz
{
public static void Main()
{
}
}
class aaa
{
abstract public void pqr();
public int i = 20;
public void abc()
{
}
}
Compiler Error
a.cs(9,22): error CS0513: ‘aaa.pqr()’ is abstract but it is contained in nonabstract class ‘aaa’
If a class has even one abstract function, then the class has to be declared abstract. An
abstract method cannot also use the modifiers static or virtual.
Only in the abstract class can we have one abstract function. Anyone who implements from an
abstract class has to write the code for its function. By default the modifier new gets added,
which makes it a new/different function.
a.cs
class zzz
{
public static void Main()
{
}
}
abstract class yyy
{
public abstract void abc();
}
class xxx : yyy
{
public override void abc()
{
base.abc();
}
}
Compiler Error
a.cs(15,1): error CS0205: Cannot call an abstract base method: ‘yyy.abc()’
You cannot call the function abc from the base class as it does not carry any code along with
it and has been declared abstract. C# does not allow you to call a function that has no code.
a.cs
class zzz
{
public static void Main()
{
yyy a = new www();
xxx b = new www();
a.abc(); b.abc();
}
}
abstract class xxx : yyy
{
public abstract new void abc();
}
Output
yyy abc
www abc
class yyy
{
public virtual void abc()
{
System.Console.WriteLine(“yyy abc”);
}
}
class www : xxx
{
public override void abc()
{
System.Console.WriteLine(“www abc”);
}
}
a.abc() will first peek (get) into the class yyy. Here it finds function abc tagged as virtual. How
many times have we repeated the above lines? Countless times. C# will then toddle (go) over to
class xxx. Here it finds to its dismay(disappointment) that the function abc is abstract i.e. there
is no code for abc and also that it is a new function, thus severing(cut) all links with the base
class. Activity stops and all hell breaks loose and the function abc from yyy gets executed.
In the case of b.abc(), as the function is new, the links to the base class are broken, we have no
choice but to call the function from www as it says override. We cannot replace the modifier
new with the keyword override for function abc in abstract class xxx .
Compiler Error
a.cs(21,7): error CS0534: ‘www’ does not implement inherited abstract member ‘xxx.abc()’
If we replace the override keyword with new in class www, we will get an error as there is no
code for the function abc. Remember the abc of yyy has nothing to do at all with that of xxx and
www.
Virtual functions run slower than non virtual functions and it is obvious that an abstract class
cannot be sealed.
a.cs
public class zzz
{
public static void Main()
{
}
}
sealed abstract class aaa
{
public abstract void abc();
}
Compiler Error
a.cs(7,23): error CS0502: 'aaa' cannot be both abstract and sealed
Download