Kao što vam je poznato, klasa ne može da nasleđuje istovremeno više osnovnih klasa. Ali zato može da implementira više interfejsa, istovremeno. Dok osnovna klasa definiše šta ona u stvari predstavlja, interfejs definiše šta klasa radi. Interfejs uopšte ni ne zna šta klasa predstavlja, nije uopšte zavisna od toga ali se interfejsi opet mogu dodati klasi i koristiti u mnogim situacijama. Interfejs je najjednostavnije rečeno ugovor koji kompletno odvaja imena i potpise metoda, propertija, indeksera, delegata i događaja od njihove implementacije. Ali interfejs ne može da sadrži polja. Na taj način osiguravate da klasa koja je u interakciji kroz određeni interfejs nema pristup internim podacima objekta. Interfejsi jesu slični apstraktnim klasama, samo što ne mogu da sadrže ništa osim navedenih potpisa i nije retkost da se interfejsi koriste zajedno sa apstraktnim klasama da bi se gradila programerska radna okruženja koja se proširuju. Interfejs, kao i apstraktna klasa se ne može instancirati. Implementacija interfejsa se u potpunosti prepušta implementirajućoj klasi. Svaki član interfejsa za razliku od klasa se podrazumeva da je javni, svaki član mora biti javni i svaki član se mora implementirati u istoj implementirajućoj klasi. Ali najvažnija osobina interfejsa je da klase mogu implementirati više interfejsa kao i što interfejs može da poziva druge interfejse. Kada se iz jednog interfejsa pozivaju drugi interfejsi, onda se to naziva re-implementation.
( Interfejsi i apstraktne klase zahtevaju implementaciju )
Programerima kojima je poznat koncept COM interfejsa, treba da znaju da postoji razlika. U C# programskom jeziku interfejsi se ne izvode iz klase IUnknown. Oni predstavljaju ugovor izražen u vidu funkcija radnog okvira .Net Framework-a i za razliku od COM interfejsa, interfejsi u C# ne predstavljaju nikakvu vrstu binarnog standarda. Interfejsi se definišu sa ključnom rečju interface i u nazivu interfejsa je uvek poželjno staviti prefiks ’I’ kako bi se znalo da je reč o interfejsu. To je jednostavno nepisano pravilo i praksa.
interface IBankAccount
{
void Withdraw(decimal amount);
void PayIn(decimal amount);
decimal Balance { get; }
}
public interface IEmployee
{
void DisplayEmployee();
}
public interface ICompany
{
void DisplayEmployee();
}
Onda bi ste metode jedino mogli da razlikujete i pozivate kastingom:
Program program = new Program();
((IEmployee)program).DisplayEmployee();
((ICompany)program).DisplayEmployee();
Zato je eksplicitno povezivanje bolje, dok implicitno se sve ređe koristi čak ga i ne preporučuju. Često se dešava da programeri mešaju ova dva načina implementacije i kad govore o implicitnoj implementaciji u stvari misle na eksplicitnu i obratno. Zato dobro pogledajte oba primera implementacije interfejsa. U velikim projektima interfejsi itekako imaju veliku vrednost i primenu i često će te se susretati sa obe implementacije.
Implicitno
implementiranje interfejsa
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace InterfaceImplicitImplementation
{
interface IBankAccount
{
void Withdraw(decimal amount);
void PayIn(decimal amount);
decimal Balance { get; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace InterfaceImplicitImplementation
{
class SaverAccount
{
private decimal balance;
public void PayIn(decimal amount)
{
balance += amount;
}
public void Withdraw(decimal amount)
{
if
(balance >= amount)
{
balance -= amount;
}
else
{
Console.WriteLine("Europe Bank Saver Account: Withdraw
attempt faild.");
}
}
public decimal Balance { get; }
public override string ToString()
{
return String.Format("Europe Bank Saver
Account: Balance = {0,6:C}", balance);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace InterfaceImplicitImplementation
{
class GoldAccount
{
private decimal balance;
public void PayIn(decimal amount)
{
balance += amount;
}
public void Withdraw(decimal amount)
{
if
(balance >= amount)
{
balance -= amount;
}
else
{
Console.WriteLine("America Bank Gold Account: Withdraw
attempt faild.");
}
}
public decimal Balance { get; }
public override string ToString()
{
return String.Format("America Bank Gold
Account: Balance = {0,6:C}", balance);
}
}
}
using System;
using static System.Console;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace InterfaceImplicitImplementation
{
class Program
{
public void DisplayEmployee() =>
Write("k");
static void Main(string[] args)
{
string FirstName = "Manuel";
string LastName = "Radovanovic";
WriteLine(Environment.NewLine + new String('-', 20) + Environment.NewLine);
WriteLine(FirstName + " " + LastName);
WriteLine(Environment.NewLine + new String('-', 20) + Environment.NewLine);
SaverAccount europeAccount = new
SaverAccount();
GoldAccount americaAccount = new
GoldAccount();
europeAccount.PayIn(250);
WriteLine(europeAccount.ToString());
europeAccount.PayIn(500);
WriteLine(europeAccount.ToString());
europeAccount.Withdraw(1000);
WriteLine(europeAccount.ToString());
europeAccount.Withdraw(400);
WriteLine(europeAccount.ToString());
WriteLine(Environment.NewLine + new String('-', 20) + Environment.NewLine);
americaAccount.PayIn(550);
WriteLine(americaAccount.ToString());
americaAccount.Withdraw(700);
WriteLine(americaAccount.ToString());
americaAccount.Withdraw(125);
WriteLine(americaAccount.ToString());
WriteLine(Environment.NewLine + new String('-', 20) + Environment.NewLine);
ReadKey();
}
}
}
--------------------
Manuel Radovanovic
--------------------
Europe Bank Saver Account: Balance = $250.00
Europe Bank Saver Account: Balance = $750.00
Europe Bank Saver Account: Withdraw attempt faild.
Europe Bank Saver Account: Balance = $750.00
Europe Bank Saver Account: Balance = $350.00
--------------------
America Bank Gold Account: Balance = $550.00
America Bank Gold Account: Withdraw attempt faild.
America Bank Gold Account: Balance = $550.00
America Bank Gold Account: Balance = $425.00
--------------------
Kako izgleda prethodni program možete pogledati i na video-u:
( C# 6.0 Tutorial - Fundamentals - 39. Interface Implicit Implementation )
Eksplicitno implementiranje interfejsa
Da bi vam bilo što jasnije, uzećemo isti prethodni program i prepraviti ga da klase implementiraju eksplicitno interfejs. Eksplicitnim implementiranje interfejsa izbegavate iste nazive metoda koje bi se mogle desiti ukoliko bi neka od navedenih klasa implemetirala još neki interfejs sa nekim istim nazivom jedne od metoda koje ste već implementirali. To se radi tako što navedete naziv interfejsa svakoj metodi koju implementirate.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace InterfaceExplicitImplementation
{
interface IBankAccount
{
void Withdraw(decimal amount);
void PayIn(decimal amount);
decimal Balance { get; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace InterfaceExplicitImplementation
{
class SaverAccount : IBankAccount
{
private decimal balance;
void IBankAccount.PayIn(decimal amount)
{
balance += amount;
}
void IBankAccount.Withdraw(decimal amount)
{
if
(balance >= amount)
{
balance -= amount;
}
else
{
Console.WriteLine("Europe Bank Saver Account: Withdraw
attempt faild.");
}
}
decimal IBankAccount.Balance { get; }
public override string ToString()
{
return String.Format("Europe Bank Saver
Account: Balance = {0,6:C}", balance);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace InterfaceExplicitImplementation
{
class GoldAccount : IBankAccount
{
private decimal balance;
void IBankAccount.PayIn(decimal amount)
{
balance += amount;
}
void IBankAccount.Withdraw(decimal amount)
{
if
(balance >= amount)
{
balance -= amount;
}
else
{
Console.WriteLine("America Bank Gold Account: Withdraw
attempt faild.");
}
}
decimal IBankAccount.Balance { get; }
public override string ToString()
{
return String.Format("America Bank Gold
Account: Balance = {0,6:C}", balance);
}
}
}
using System;
using static System.Console;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace InterfaceExplicitImplementation
{
class Program
{
static void Main(string[] args)
{
string FirstName = "Manuel";
string LastName = "Radovanovic";
WriteLine(Environment.NewLine + new String('-', 20) + Environment.NewLine);
WriteLine(FirstName + " " + LastName);
WriteLine(Environment.NewLine + new String('-', 20) + Environment.NewLine);
IBankAccount europeAccount = new
SaverAccount();
IBankAccount americaAccount = new
GoldAccount();
europeAccount.PayIn(250);
WriteLine(europeAccount.ToString());
europeAccount.PayIn(500);
WriteLine(europeAccount.ToString());
europeAccount.Withdraw(1000);
WriteLine(europeAccount.ToString());
europeAccount.Withdraw(400);
WriteLine(europeAccount.ToString());
WriteLine(Environment.NewLine + new String('-',20) + Environment.NewLine);
americaAccount.PayIn(550);
WriteLine(americaAccount.ToString());
americaAccount.Withdraw(700);
WriteLine(americaAccount.ToString());
americaAccount.Withdraw(125);
WriteLine(americaAccount.ToString());
WriteLine(Environment.NewLine + new String('-', 20) + Environment.NewLine);
ReadKey();
}
}
}
Kao što vidite kod eksplicitnog implementiranje metoda, svakom nazivu metode je dodat naziv interfejsa i odvojen tačkom ’.’ i tako nema konfuzije kako god da se zovu druge metode drugih interfejsa koje takođe treba implementirati. Kad pokrenete navedeni program rezultat je apsolutno isti kao u prethodnom programu, samo je implementacija interfejsa drugačija.
--------------------
Manuel Radovanovic
--------------------
Europe Bank Saver Account: Balance = $250.00
Europe Bank Saver Account: Balance = $750.00
Europe Bank Saver Account: Withdraw attempt faild.
Europe Bank Saver Account: Balance = $750.00
Europe Bank Saver Account: Balance = $350.00
--------------------
America Bank Gold Account: Balance = $550.00
America Bank Gold Account: Withdraw attempt faild.
America Bank Gold Account: Balance = $550.00
America Bank Gold Account: Balance = $425.00
--------------------
Kako izgleda prethodni program možete pogledati i na video-u:
( C# 6.0 Tutorial - Fundamentals - 40. Interface Explicit Implementation )
Kad se koristi jednostavna klasa, kad apstraktna klasa a kad interfejs?
Samo programerskim iskustvom možete pretpostaviti kad vam je najbolje da koristite jednostavnu klasu, kad je bolje da klasu proširite apstraktnom klasom ili interfejsom. Retko se dešava da programer izabere samo jedan ili drugi način za rešenje nekog problema, već je češća situacija da je rešenje kombinacija različitih pristupa. Do nekih promena dolazi i testiranjem. Na primer, ukoliko postoji razumna količina zajedničkih funkcionalnosti ili kad imate mnoštvo istog koda koje je najbolje grupisati na jednom mestu, onda vam savetujem da koristite apstraktnu klasu. Apstraktne klase nameću strožiju strukturu koda i definišu podrazumevani oblik realizovanja. Međutim ako poslovna logika nalaže mnoštvo klasa i njihovo nasleđivanje tada su interfejsi rešenje. Ukoliko nemate potrebe za proširivanjem i nadogradnjama poslovanja, onda je najbolje klasu ostaviti na nivou jednostavne klase. Sve ostalo je na nivou poslovne logike.
No comments:
Post a Comment