Corso C# – Lezione n.4

Introduzione

Nella lezione n.4, l’argomento principale è la programmazione ad oggetti in C#, in particolare le classi e le interfacce. Le interfacce costituiscono il nuovo concetto che viene introdotto in questa lezione.
Con un esempio molto articolato sarai guidato nello sviluppo di progetti mediante le classi e le interfacce.

Argomenti

Le interfacce nella programmazione ad oggetti in generale

Nella programmazione ad oggetti è stato affrontato il tema della definizione di una classe e dei membri della stessa quali i metodi, e gli attributi. Molto spesso si lavora con molte classi ove sovente sono utilizzati metodi che concettualmente svolgono lo stesso compito ma con dati di tipo differente.
Poniamo come esempio una classe che memorizza due stringhe e un’altra due numeri interi. Nella prima e nella seconda classe potremmo definire un metodo “confronta” che verifica se un membro della classe è precedente o successivo ad un altro (nella prima classe il confronto avviene fra stringhe con criterio di ordinamento alfabetico e nella seconda classe il confronto è fra numeri).
Gli elementi in comune fra le due classi è l’operazione di confronto che avviene con dati diversi.
Per generalizzare questa operazione si potrebbe definire appunto un’interfaccia che genericamente indichi le caratteristiche del metodo e permetta quindi di implementare tale metodo per ogni classe con lo stesso nome e con argomenti diversi.
L’uso delle interfacce permette di stabilire un “contratto” fra la classe e i suoi membri in quanto nella classe è obbligatorio implementare i metodi definiti nell’interfaccia in modo astratto.
Inoltre l’interfaccia consente anche di introdurre concetti di programmazione “Generica” che sono indipendenti dai tipi di dati utilizzati per la relativa implementazione.
Questo concetto di programmazione “Generica” sarà ripreso nelle prossime lezioni.

Le interfacce in C#

Per definire un’interfaccia in C# è possibile definirla all’interno di una singola classe (non è una scelta conveniente in quanto è poco generalizzata) o in un file seprato che possiamo aggiungere al nostro progetto “C#”. Inoltre tutti i metodi dell’interfaccia, poiché devono essere accessibili da tutte le classi che la utilizzano, sono intrinsecamente “pubblici”. Nella dichiarazione dell’interfaccia la clausola “public” viene omessa mentre nell’implementazione diversificata in ogni classe la clausola “public” è obbligatoria.
La sintassi di un’interfaccia è molto semplice:
interface nome
{
metodi;
}
o in alternativa in modo ancor più genrico con il tipo “T” che indica un qualunque tipo di elemento “classe”, “struct” “tipo”. Sarà poi ripreso nelle prossime lezioni, la sintassi è:
interface nome<T>
{
metodi;
}

La programmazione ad oggetti con le interfacce

Una volta definita l’interfaccia occorre richiamarla all’interno della dichiarazione di classe ove si desidera venga utilizzata.
La sintassi è:
[modificatore accesso] class nome classe : nome interfaccia
{ elenco metodi dell’interfaccia con modificatore public
elenco metodi e attributi della classe
}
Una volta implementati i metodi sono richiamati negli oggetti e/o istanze di classe nel medesimo modo in cui sono richiamati i metodi (in effetti a livello di classe sono la stessa tipologia).

Caso di studio

Come soluzione viene sviluppato un progetto composto da una classe di nome “Frazioni”, un interfaccia con due operazioni “Confronto” e “Somma” che sono appunto le operazioni di confronto fra frazioni per verificare quale frazione è più grande o se sono equivalenti (ad esempio 1/2 è equivalente a 2/4) e la somma fra frazioni (ad esempio 1/2+3/4=5/4).
Per fare questo sarà utilizzato il concetto di interfaccia e progettata una classe idonea a implementare i due metodi.
Il Diagramma UML del progetto è rappresentato nella figura sotto stante:

Rappresentazione UML della Classe Frazioni, dell sua interfaccia Ioperazioni e della classe  Program che permette il test del progetto.

Codice Sorgente del progetto

Il codice sorgente è strutturato in tre file il primo è il codice dell’interfaccia:

using System;
using System.Collections.Generic;
using System.Text;

namespace Progetto_Lezione_n4_2
{
    interface IOperazioni
    {
         int Confronto();
        void Somma();


    }
}

In questo codice sono definiti i metodi dell’interfaccia in modo molto generico solo con le intestazioni.
Il codice della classe Frazioni è:

using System;
using System.Collections.Generic;
using System.Text;

namespace Progetto_Lezione_n4_2
{
   
    class Frazioni: IOperazioni
    {
        private int num1;
        private int num2;
        private int den1;
        private int den2;
        private int num3;
        private int den3;
        public int MinimoComuneMultiplo(int x, int y)
        {
            int ris = 1;
            while (y != 0)
            {
                //Console.WriteLine("X,Y,Ris:" + x + "," + y + "," + ris + " ");
                ris = y;
                y = x % y;
                x = ris;
            }
            ris = (den1 * den2) / ris;
            return ris;
        }
        public int Confronto()
        {
            float r1, r2;
            r1 = ((float)this.num1) /((float)this.den1);
            r2 = ((float)this.num2) /((float)this.den2);
            if (r1 < r2)
                return 2;
            if (r1 > r2)
                return 1;
            else
             return 0;
            ;
        }
        public void Somma()
        {
            
            int mcm=MinimoComuneMultiplo(den1,den2);
            int n1,n2;
            //Console.WriteLine("M.C.M: " + mcm);
            n1 = (mcm / den1) * num1;
            n2 = (mcm / den2) * num2;
            den3 = mcm;
            num3 = n1 + n2;
            Console.WriteLine(toString(num3, den3));
            
        }
        public Frazioni(int x,int y, int w, int z)
        {
            num1 = x;
            den1 = y;
            num2 = w;
            den2 = z;
        }
        public string toString(int x,int y)
        {
            string r;
            r = Convert.ToString(x) + "/" + Convert.ToString(y);
            return r;
        }
        
     
        public int _Den1
        {
            get { return den1; }
            set { den1 = value; }

        }
        public int _Num1
        {
            get { return num1; }
            set { num1 = value; }
        }
        public int _Den2
        {
            get { return den2; }
            set { den2 = value; }

        }
        public int _Num2
        {
            get { return num2; }
            set { num2 = value; }
        }
    }
}

Link di affiliazione

Il codice sorgente della classe contiene l’implementazione dei metodi definiti nell’interfaccia. Ovviamente per eseguire la somma fra frazioni occorre calcolare il minimo comune multiplo e per questo è stata utilizzato il metodo “MinimoComuneMultiplo(int x, int y) che calcola mediante un algoritmo noto che attraverso l’uso del Massimo Comune Divisore calcola il minimo comune multiplo come rapporto fra il prodotto di a per b e il MCD.
Per il confronto fra frazioni sono calcolati i rapporti r1 e r2 e se i rapporti coincidono le frazioni sono “equivalenti”, mentre se r1 è superiore a r2 la prima frazione è più grande altrimenti vale il contrario.
Nella classe sono state definite anche le proprietà get e set per gli attributi della classe. Le proprietà consentono di accedere in lettura e scrittura agli attributi della classe mediante la notazione dei metodi di un oggetto.
La classe Program di test della classe e dell’interfaccia prevede l’inserimento dei dati l’istanziamento di una variabile di classe Frazione che mediante il costruttore definisce le due frazioni di partenza.
Il metodo toString definito nella classe permette la stampa della frazione corretto.

Video della lezione n.4 – Corso C# – prima parte