Saturday, March 2, 2013

C# interface-i

Interfejsi su kao ugovor. On definiše metode, property-e, itd. koje svaka klasa mora da implementira ako implementira i taj interfejs. Evo jedan primer iz prakse. Definišeš interfejs za snimanje objekta Student u bazu podataka.
public interface IStudentRepository
{
    Student GetById(int id);
    List GetAll();
    void Save(Student student);
    void Delete(int id);
}
I sada hoćemo da napravimo konkretnu implementaciju tog interfejsa
public class StudentRepositoryEntityFramework : IStudentRepository
{
    public Student GetById(int id)
    {
        // insert some code here
    }

    public List GetAll()
    {
        // insert some code here
    }

    public void Save(Student student)
    {
        if (student.Id > 0)
            Update(student);
        else
            Create(student);
    }

    private void Create(Student student)
    {
        // insert some code here
    }

    private void Update(Student student)
    {
        // insert some code here
    }

    public void Delete(int id)
    {
        // insert some code here
    }
}
Klasa StudentRepositoryEntityFramework je sklopila ugovor sa interfejsom IStudentRepository. To znači da mora da implementira sve metode koje su definisane u interfejsu IStudentRepository i te metode moraju biti public. Save metoda ne može biti private, internal ili protected, ona mora biti public. Tvoja konkretna implementacija može da sadrži i neke metode koje nisu definisane u interfejsu, kao što su Create, Update, itd., ali sve metode koje su definisane u interfejsu moraju biti implementirane i moraju biti public, ok? Interfejsi se najviše koriste kod Dependency injection i Inversion of control pattern-a. Dosta je komplikovano u početku da se skapira, ali poenta je sledeća: Sve što radiš, radiš sa interfejsima, a ne sa konkretnim implementacijama. Zašto? 1. Zbog Unit Testova. Implementaciju možeš uvek da zameniš sa nekim fake objektom. 2. Ako želiš da promeniš implementaciju, tj. nećeš više da koristiš EntityFramework već NHibernate. Ako na 50 mesta u kodu koristiš StudentRepositoryEntityFramework umesto IStudentRepository, onda ćeš na tih 50 mesta morati da zameniš StudentRepositoryEntityFramework sa StudentRepositoryNHibernate. Ako na 50 mesta u kodu koristiš IStudentRepository, onda ćeš izmenu morati da napraviš samo na jednom mestu (na mestu gde se definiše koja klasa se instancira za dati interfejs)! Zasto bi klasa implementirala interfejs da bi se mogla uporediti dva objekta, zasto jednostavno bez interfejsa se ne napravi metod koji ce uporedjivati objekte?

No comments:

Post a Comment