C # - Polimorfismo

La parola polymorphismsignifica avere molte forme. Nel paradigma della programmazione orientata agli oggetti, il polimorfismo è spesso espresso come "un'interfaccia, più funzioni".

Il polimorfismo può essere statico o dinamico. Nelstatic polymorphism, la risposta a una funzione viene determinata in fase di compilazione. Neldynamic polymorphism, viene deciso in fase di esecuzione.

Polimorfismo statico

Il meccanismo di collegamento di una funzione con un oggetto durante la fase di compilazione è chiamato associazione anticipata. È anche chiamato binding statico. C # fornisce due tecniche per implementare il polimorfismo statico. Sono -

  • Sovraccarico delle funzioni
  • Sovraccarico dell'operatore

Discuteremo il sovraccarico degli operatori nel prossimo capitolo.

Funzione sovraccarico

È possibile avere più definizioni per lo stesso nome di funzione nello stesso ambito. La definizione della funzione deve differire l'una dall'altra per i tipi e / o il numero di argomenti nell'elenco degli argomenti. Non è possibile eseguire l'overload di dichiarazioni di funzione che differiscono solo per il tipo restituito.

L'esempio seguente mostra l'utilizzo di function print() per stampare diversi tipi di dati -

using System;

namespace PolymorphismApplication {
   class Printdata {
      void print(int i) {
         Console.WriteLine("Printing int: {0}", i );
      }
      void print(double f) {
         Console.WriteLine("Printing float: {0}" , f);
      }
      void print(string s) {
         Console.WriteLine("Printing string: {0}", s);
      }
      static void Main(string[] args) {
         Printdata p = new Printdata();
         
         // Call print to print integer
         p.print(5);
         
         // Call print to print float
         p.print(500.263);
         
         // Call print to print string
         p.print("Hello C++");
         Console.ReadKey();
      }
   }
}

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

Printing int: 5
Printing float: 500.263
Printing string: Hello C++

Polimorfismo dinamico

C # consente di creare classi astratte utilizzate per fornire un'implementazione parziale della classe di un'interfaccia. L'implementazione è completata quando una classe derivata eredita da essa.Abstractle classi contengono metodi astratti, che vengono implementati dalla classe derivata. Le classi derivate hanno funzionalità più specializzate.

Ecco le regole sulle classi astratte:

  • Non è possibile creare un'istanza di una classe astratta

  • Non è possibile dichiarare un metodo astratto al di fuori di una classe astratta

  • Quando viene dichiarata una classe sealed, non può essere ereditato, le classi astratte non possono essere dichiarate sigillate.

Il seguente programma mostra una classe astratta:

using System;

namespace PolymorphismApplication {
   abstract class Shape {
      public abstract int area();
   }
   
   class Rectangle:  Shape {
      private int length;
      private int width;
      
      public Rectangle( int a = 0, int b = 0) {
         length = a;
         width = b;
      }
      public override int area () { 
         Console.WriteLine("Rectangle class area :");
         return (width * length); 
      }
   }
   class RectangleTester {
      static void Main(string[] args) {
         Rectangle r = new Rectangle(10, 7);
         double a = r.area();
         Console.WriteLine("Area: {0}",a);
         Console.ReadKey();
      }
   }
}

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

Rectangle class area :
Area: 70

Quando hai una funzione definita in una classe che desideri sia implementata in una o più classi ereditate, usi virtualfunzioni. Le funzioni virtuali potrebbero essere implementate in modo diverso in diverse classi ereditate e la chiamata a queste funzioni verrà decisa in fase di esecuzione.

Il polimorfismo dinamico è implementato da abstract classes e virtual functions.

Il seguente programma lo dimostra:

using System;

namespace PolymorphismApplication {
   class Shape {
      protected int width, height;
      
      public Shape( int a = 0, int b = 0) {
         width = a;
         height = b;
      }
      public virtual int area() {
         Console.WriteLine("Parent class area :");
         return 0;
      }
   }
   class Rectangle: Shape {
      public Rectangle( int a = 0, int b = 0): base(a, b) {

      }
      public override int area () {
         Console.WriteLine("Rectangle class area :");
         return (width * height); 
      }
   }
   class Triangle: Shape {
      public Triangle(int a = 0, int b = 0): base(a, b) {
      }
      public override int area() {
         Console.WriteLine("Triangle class area :");
         return (width * height / 2); 
      }
   }
   class Caller {
      public void CallArea(Shape sh) {
         int a;
         a = sh.area();
         Console.WriteLine("Area: {0}", a);
      }
   }  
   class Tester {
      static void Main(string[] args) {
         Caller c = new Caller();
         Rectangle r = new Rectangle(10, 7);
         Triangle t = new Triangle(10, 5);
         
         c.CallArea(r);
         c.CallArea(t);
         Console.ReadKey();
      }
   }
}

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

Rectangle class area:
Area: 70
Triangle class area:
Area: 25