DEV Community

Vidisha Parab
Vidisha Parab

Posted on

Abstract or Virtual ?

We have come across abstract and virtual methods while programming and I often get startled when I see these two keywords. Whenever I try to look up for them a lot of "tabular comparisons" are being thrown at me, distinguishing between the two without highlighting why they are so ?

I try to put together my understanding below.

Abstract and virtual methods are a part of a concept called as polymorphism from object oriented programming. Polymorphism is further derived from the idea of Inheritance.
Why do we need Inheritance ? Inheritance is supposed to be the best feature of OOP. We can extend and reuse the capabilities of a class further as per the business needs i.e. writing less code ! How does polymorphism fits into this ? Say we have a class which outlines how a pizza should be . It also has a method called Prepare, data properties for the pizza name and price. In its most basic form, this method would output a plain pizza.

 public class Pizza
    {
        public string Name { get; set; }
        public int Price { get; set; }
        public void Prepare()
        {
            Console.WriteLine("Here is a pizza dough base with some tomato sauce spread on it !");
        }
    }
Enter fullscreen mode Exit fullscreen mode

Someone walks up to us and tells us that now we also have to prepare Hawaiian and Pepperoni pizza. One option would be to make separate implementations for them.But we already have a Pizza class, which has a method Prepare that outputs pizza in the basic form and also it has data properties which will help us to store the name and price, why not inherit from it (remember -lesser code)? But won't the method Prepare give us a basic pizza ? Override it !

We can override the method Prepare to have two different behaviors - one which would give us the Hawaiian pizza and the other which would give us the Pepperoni pizza. This right here is polymorphism - The Prepare method behaving differently in different contexts.

 public class HawaiianPizza : Pizza
    {
        /*the field like name and price need not be written here as we inherit 
          them impiclitly from the parent Pizza class*/

       //overridden implementation of Prepare method to give us a hawaiian pizza
    }
Enter fullscreen mode Exit fullscreen mode
 public class PepperoniPizza : Pizza
    {
       /*the field like name and price need not be written here as we inherit 
          them impiclitly from the parent Pizza class*/

       //overridden implementation of Prepare method to give us a Pepperoni  pizza
    }
Enter fullscreen mode Exit fullscreen mode

Now that we established what polymorphism and inheritance is, it is equally important to know how to achieve those. Inheritance is when a class derives from another class or an interface.The class which other classes derive from is called as a base class. Now this base class can be either an abstract class or a concrete class. Whenever a class is incomplete with at least one member not implemented then it is called as an abstract class. For e.g. the class Pizza below

 public abstract class Pizza
    {
        public string Name { get; set; }
        public int Price { get; set; }
        public abstract void Prepare();
    }
Enter fullscreen mode Exit fullscreen mode

Here you can see that the method Prepare has no body or implementation (don't fret over the keyword abstract in that method, we will come to it soon !) . Given that an abstract class is incomplete , there is no point in creating any instance of it . What if an instance is created and someone calls the Prepare method ?
Bam ! It would be a disaster since we lack its implementation. And there we have it - Abstract classes can never be instantiated (the very first point of distinction the search results provide us). Also some search result tell us that "abstract classes" should be defined by the abstract keyword. well thank you !

Secondly, a base class could also be a concrete class. A concrete class is complete with all its implementations in place- just like a normal class and hence it can be instantiated !

Coming to our abstract and virtual methods.

By default any method be it of an abstract class or a concrete class cannot be overridden even if the class is inherited by some other class. So if we want a child class to have its own implementation of a particular base class method then we do so by marking the base class method as abstract or virtual -meaning allowing it to be overridden.

Depending on the pizza which we order,say the price would vary , there might be certain discounts on a particular type of pizza, or some logic involved in calculating the price of the pizza. In the base class - Pizza we don't want to handle that , we just want our Pizza class to give us out a pizza base with a tomato sauce layered on it. In this case we will declare a method CalculatePrice as abstract

public abstract int CalculatePrice();

.

Whenever we want the child classes to deal with implementation of a particular method we mark the method as an abstract.

When doing so, we will only define the signature of the method in the parent class

Now the implications of this -

  1. Like we established that the abstract classes are incomplete , abstract methods are also incomplete ! Abstract methods do not have any default method implementation.

  2. Given this any class inheriting from Pizza must override this method ! Obviously it wouldn't make sense to have a method which is just a signature, without any job to do ! (Think about interfaces , how it is required for us to implement them) It is mandatory to override abstract methods !

  3. Also since it is an incomplete method(without any implementation) it is pointless to have it in a concrete class (because concrete classes are complete and we cannot introduce this kind of ambiguity in them !). Hence the reason Abstract methods can only be used in an abstract class.
    Alt Text

What about virtual methods ? No matter what, we want to have a basic pizza - a pizza dough base and tomato sauce on it (a l'il bit of cheese doesn't hurt as well!). Here I am sure that under any case I need to have that and not depend on the child classes for the implementation. I will go ahead and mark the method as virtual

Whenever we want to have a default behavior or implementation of a method in a parent class we mark this method as virtual

When we mark it as a virtual method ,in addition to giving a default implementation we also give liberty to the child classes to override it and have their own implementation defined if the default one doesn't meet their needs.

 public abstract class Pizza
    {
        public string Name { get; set; }
        public int Price { get; set; }
        public abstract int CalculatePrice();
        public virtual void Prepare()
        {
            Console.WriteLine("Here is a pizza dough base with some tomato sauce spread on it !");
        }
    }
Enter fullscreen mode Exit fullscreen mode

Implications

  1. Though a default implementation is given in the parent class, the child classes can still have their implementations thus overriding the one given by the parent class.
  2. Since a virtual method is complete with a default implementation it is not mandatory for the child classes to override it (have their own implementation). Virtual methods don't necessarily have to be overridden . If you don't override the Prepare method in the Pepperoni class you are not going to get Pepperoni,You get a basic Pizza !
  3. Also since they have a fully functional implementation , they can be a part of both abstract and concrete class !

Here we have inherited class PepperoniPizza from the class Pizza .You also see the inherited members of the Pizza class
Alt Text

Hope you find this useful.Any suggestions or fixes are always welcome ! :)

Top comments (1)

Collapse
 
deshaware profile image
Swapnil Deshaware

Nice Article