Take advantage of polymorphism to isolate interface from implementation and promote flexibility in your designs Polymorphism refers to the ability to present the same interface for different forms. Although the concept of polymorphism is the same in all programming languages that support it, its implementation differs from one language to another. The three types of polymorphism are overloading, parametric, and inclusion. Polymorphism helps to promote flexibility in designs by allowing the same method to have different implementations. In essence, you can leverage polymorphism to separate interface from implementation. It promotes code reuse and separation of concerns in your application. Overloading polymorphism is a type that exists in classes that are independent of each other — they are not related (inheritance, dependency, etc.) to each other in any way. As an example, you can have two distinct classes not related in any way with each other and having a method with the same name. Operator overloading is an example of this type of polymorphism. Parametric polymorphism, or template polymorphism, is a type where you have more than one method in your class with identical names but varying parameters, i.e., they all have the same method names, but they differ in the parameters. Inclusion polymorphism is also known as redefinition or method overriding. In this type of polymorphism, a sub class can redefine a method of the base class. This ability is also known as specialization. Parametric polymorphism This refers to the form of polymorphism where you have more than one method in your class that has the same name but they differ in their method signatures. A method signature comprises of the return type of the method, the type of the parameters to the method and the sequence of these parameters. Hence, a method that accepts an integer and a character as an argument differs in the signature from another method that accepts a character and an integer as arguments even though the return types of both these methods (having identical method names) are the same. The compiler determines the exact method to be called by comparing the method signatures of the overloaded methods. The following code listing illustrates how method overloading can be implemented. public enum Severity { Informational, Warning, Critical } public class Logger { public void Log(string message) { //Some code } public void Log(string message, Severity severity) { //Some code } } Refer to the code listing above. Note how the Log() method has been overloaded. This is an example of compile time polymorphism. Inclusion polymorphism Inclusion polymorphism, or method overriding, can be achieved in C# using virtual methods. In method overriding, you have methods having identical signatures present in both the base and the derived classes. You would typically want to use virtual methods to implement run-time polymorphism or late binding. Note that a virtual method is one that is declared as virtual in the base class and you can allow the subclasses of the type to override the virtual method(s). The following code snippet shows two classes — the base class named Logger that contains a virtual method called Log and a derived class named FileLogger that extends the Logger class and overrides the Log method of the base class. public class Logger { public virtual void Log(string message) { Console.WriteLine("Inside the Log method of the base class Logger"); } } public class FileLogger : Logger { public override void Log(string message) { Console.WriteLine("Inside the Log method of the FileLogger class"); } } This is an example of method overriding. Both the base and the derived classes have the same method with identical signatures. We use method overriding to implement run time polymorphism or late binding. The following code snippet shows how the Log method can be called using a reference of the base class. static void Main(string[] args) { Logger logger = new FileLogger(); logger.Log("Hello World!"); Console.ReadKey(); } When you execute the above code snippet, the Log method of the derived class, i.e., the Filelogger class would be invoked. If the Log method wasn’t declared as virtual in the base class, the base version of the Log method would have been called instead. Since this binding occurs late at run-time, this type of polymorphism is known as run-time polymorphism or late binding. Related content feature 14 great preprocessors for developers who love to code Sometimes it seems like the rules of programming are designed to make coding a chore. Here are 14 ways preprocessors can help make software development fun again. By Peter Wayner Nov 18, 2024 10 mins Development Tools Software Development feature Designing the APIs that accidentally power businesses Well-designed APIs, even those often-neglected internal APIs, make developers more productive and businesses more agile. By Jean Yang Nov 18, 2024 6 mins APIs Software Development news Spin 3.0 supports polyglot development using Wasm components Fermyon’s open source framework for building server-side WebAssembly apps allows developers to compose apps from components created with different languages. By Paul Krill Nov 18, 2024 2 mins Microservices Serverless Computing Development Libraries and Frameworks news Go language evolving for future hardware, AI workloads The Go team is working to adapt Go to large multicore systems, the latest hardware instructions, and the needs of developers of large-scale AI systems. By Paul Krill Nov 15, 2024 3 mins Google Go Generative AI Programming Languages Resources Videos