úterý 23. listopadu 2010

Proč použít Interface dohromady s abstraktní třídou

Hodně často se setkávám v kódu s tím, že vývojáři upřednostňují programování rozhraním. Především je to v případech kdy kód nabízí možnost rozšíření. Bohužel tohle není moc šťastný přístup a to z důvodů zpětně kompatibility. Ukážeme si to na následujícím příkladu.

public class Registry {
 public List<Plugin> plugins;
}
public interface Plugin {
 public void doSomehing();
}
public class PluginA implements Plugin {
 public void doSomehing();
}

Pokud tohle uděláte máte zaděláno na problém. Kdykoliv se v budoucnu rozhodnete přidat do rozhraní Plugin nějakou novou metodu automaticky tím rozbijete jakoukoliv třídu implementující toto rozhraní. V našem případě PluginA. Kolikrát tím rozbijete i kód, o kterém nemáte ani páru. V případě vlastního kódu je to problém rovnající se velikosti code base, ve které to dohledáváte.

Vždycky proto preferujte poskytnutí rozhraní s abstraktní třídou, která toto rozhraní implementuje.

public abstract AbstractPlugin implements Plugin {
 public void doSomehing(){}
}

Díky tomu můžete případné rozšíření jednoduše přidat do rozhraní a poskytnout defaultní implementaci. Pokud už je to opravdu zásadní zásah do rozhraní popřemýšlejte spíše o novém rozhraní, které bude odvozené z toho původního.

Pokud vás napadlo použít jenom abstraktní třídu namísto rozhraní, pak to není také moc šťastné řešení neboť je to příliš restriktivní. Případné rozšíření musí vždy dědit z vaší třídy. Rozhraní s abstraktní třídou proto nabízí nejlepší kombinaci.