Interface: podstata, kontrakty v Javě a Kotlinu pro Android

Autor: IT Sectr Publikováno: 2026-02-18 Doba čtení: 9 min

Interface — je kontrakt definující sadu abstraktních metod, které musí třída implementovat. V Javě a Kotlinu jsou rozhraní hlavním mechanismem abstrakce a polymorfismu. V Javě 8+ mohou rozhraní obsahovat default a static metody, v Kotlinu — výchozí implementace. Podle Google Android Developers (2025) se rozhraní používají v 90% Android projektů k definování vrstev architektury — repozitářů, UseCase a služeb.

Hlavní body

  • Interface — abstraktní typ definující signatury metod bez implementace (před Java 8)
  • Implements — klíčové slovo spojující třídu s rozhraním; třída může implementovat více rozhraní
  • Default method — metoda s implementací v Java rozhraní, přidaná v Javě 8 pro zpětnou kompatibilitu
  • Kotlin interface podporuje vlastnosti s gettery a implementace metod, nahrazující abstract class v mnoha scénářích
  • Markup interface — prázdné rozhraní používané jako značka (Serializable, Cloneable, RandomAccess)

Co je Interface v Javě a Kotlinu?

Interface — je referenční typ obsahující abstraktní metody, konstanty a výchozí metody. Třída implementující rozhraní je povinna poskytnout implementaci všech jeho abstraktních metod. V Javě rozhraní nemůže mít stav (pole instance), Kotlin toto omezení také dodržuje, ale podporuje vlastnosti s přístupovými metodami.

Java
public interface Repository {
    T findById(Long id);
    List findAll();
    T save(T entity);
    void deleteById(Long id);
    
    default long count() {
        return findAll().size();
    }
}

@Entity
public class UserEntity {
    private Long id;
    private String email;
    // gettry a settry
}

public class UserRepositoryImpl implements Repository {
    private final EntityManager em;
    
    public UserEntity findById(Long id) {
        return em.find(UserEntity.class, id);
    }
    
    public List findAll() {
        return em.createQuery("FROM UserEntity", UserEntity.class)
                .getResultList();
    }
    // ostatní metody
}

Repository<T> — generické rozhraní s CRUD metodami. Výchozí metoda count() poskytuje výchozí implementaci, kterou lze přepsat. UserRepositoryImpl implementuje rozhraní pomocí EntityManager pro přístup k datům. Tento přístup umožňuje testovat datovou vrstvu přes mock rozhraní bez skutečné databáze.

Interface vs abstract class: kdy co zvolit

Volba mezi rozhraním a abstraktní třídou závisí na existenci společného stavu a vztazích mezi typy. Rozhraní definuje kontrakt (co třída může dělat), abstraktní třída — společnou implementaci (co třída je).

KritériumInterfaceAbstract Class
Stav (pole)Pouze static final konstantyAno, libovolná pole
KonstruktoryNeAno
Vícenásobná dědičnostAno (implements)Ne (extends jeden)
Modifikátory přístupupublic (Java 8-), default metodyVšechny (private, protected, public)
Kdy použítKontrakt pro nesouvisející třídySpolečný základ pro příbuzné třídy

V Clean Architecture jsou rozhraní umístěna ve vnitřní vrstvě (domain) a implementace — ve vnější (data). To umožňuje dodržovat Pravidlo závislosti: vnější vrstva závisí na vnitřní, ne naopak. Abstraktní třídy se častěji používají pro šablonové metody (Template Method pattern).

Interface v Kotlinu: vlastnosti a delegáti

Kotlin rozhraní jsou flexibilnější než Java: mohou deklarovat abstraktní vlastnosti a poskytovat implementace metod. Na rozdíl od Javy Kotlin podporuje delegování pomocí klíčového slova by, což výrazně snižuje boilerplate při implementaci vzoru Delegate.

Kotlin
interface ApiService {
    val baseUrl: String  // abstraktní vlastnost
    
    suspend fun fetchData(): Result>
    
    fun getEndpoint(path: String): String {
        return "$baseUrl/$path"  // výchozí implementace
    }
}

class RetrofitApiService(
    override val baseUrl: String
) : ApiService {
    private val client = Retrofit.Builder()
        .baseUrl(baseUrl)
        .build()
    
    override suspend fun fetchData(): Result> {
        // implementace požadavku
    }
}

// Delegování pomocí by
interface Logger {
    fun log(message: String)
}

class ConsoleLogger : Logger {
    override fun log(message: String) = println(message)
}

class UserService(logger: Logger) : Logger by logger

UserService implementuje rozhraní Logger pomocí delegování (by). Všechna volání log() jsou přesměrována na objekt logger bez psaní wrapper metod. Toto je příklad kompozice, která by v Javě vyžadovala 5-10 řádků boilerplate kódu.

Interface v Clean Architecture Android

Clean Architecture pro Android jasně rozděluje aplikaci na vrstvy. Rozhraní hrají roli hranic mezi vrstvami: Domain definuje rozhraní repozitářů a UseCase, Data poskytuje implementace. To umožňuje výměnu implementací bez změny obchodní logiky — klíčová výhoda při migraci z Room na Firebase nebo z REST na GraphQL.

Kotlin
// Domain vrstva — rozhraní (kontrakt)
interface UserRepository {
    suspend fun getUser(id: String): User
    suspend fun updateUser(user: User)
}

// Domain vrstva — use case (závisí na rozhraní)
class GetUserUseCase(
    private val repository: UserRepository
) {
    suspend operator fun invoke(id: String): Result {
        return runCatching { repository.getUser(id) }
    }
}

// Data vrstva — implementace
class UserRepositoryImpl(
    private val api: UserApi,
    private val dao: UserDao
) : UserRepository {
    override suspend fun getUser(id: String): User {
        val cached = dao.getUser(id)
        if (cached != null) return cached
        val remote = api.fetchUser(id)
        dao.insertUser(remote)
        return remote
    }
    // updateUser...
}

UserRepository — rozhraní v domain vrstvě. GetUserUseCase závisí na rozhraní, ne na implementaci. UserRepositoryImpl v data vrstvě implementuje rozhraní a kombinuje API s lokální databází. Taková architektura umožňuje testovat UseCase s mock repozitářem bez konfigurace databáze nebo sítě.

Default a static metody v Javě 8+

Default metody byly přidány v Javě 8 pro evoluční rozšíření rozhraní bez porušení zpětné kompatibility. Pokud by ArrayList neimplementoval novou metodu stream() přidanou do Collection, starý kód by fungoval dál. Static metody v rozhraních slouží pro utility související s rozhraním — alternativa k utilitním třídám.

Java
public interface Vehicle {
    void start();
    void stop();
    
    default void honk() {
        System.out.println("Beep!");
    }
    
    static Vehicle of(String type) {
        if ("car".equals(type)) return new Car();
        return new Bicycle();
    }
    
    // konstanta
    String CATEGORY = "transport";
}

Default metody řeší problém diamantu (diamond problem): pokud třída implementuje dvě rozhraní se stejnou default metodou, kompilátor vyžaduje explicitní přepsání. Static metody jsou volány přes jméno rozhraní — Vehicle.of("car"), bez instance.

Typické chyby při navrhování rozhraní

Chyby při navrhování rozhraní vedou k křehkému kódu, obtížím při testování a porušení SOLID. Podívejme se na tři časté problémy.

Interface Pollution — příliš mnoho metod v jednom rozhraní

Rozhraní s 15+ metodami porušuje Interface Segregation Principle (ISP). Příklad — staré java.util.Dictionary s 10+ metodami. Řešení: rozdělit na několik malých rozhraní — ReadableRepository, WritableRepository, SearchableRepository. Klient (služba) závisí pouze na metodách, které potřebuje.

Přílišná abstrakce — rozhraní pro každou třídu

Vytváření rozhraní pro každou třídu bez skutečné potřeby polymorfismu je anti-vzor Interface overkill. Znak: rozhraní má právě jednu implementaci a v projektu nejsou plány na přidání alternativ. Řešení: přidejte rozhraní pouze když se objeví druhá varianta implementace nebo potřeba mocku pro testy.

Často kladené otázky

Čím se liší interface od abstract class v Javě?

Interface definuje pouze kontrakt (signatury metod), nemůže mít stav a podporuje vícenásobnou dědičnost. Abstract class může obsahovat pole, konstruktory a implementované metody, ale třída může dědit pouze jednu abstraktní třídu. Od Javy 8 rozhraní získala default a static metody, čímž se rozdíl zmenšil.

Může rozhraní dědit jiné rozhraní?

Ano, v Javě a Kotlinu rozhraní podporují dědičnost. public interface AdvancedRepository<T> extends Repository<T>, Pageable — rozhraní spojující dvě další. Třída implementující AdvancedRepository musí implementovat všechny metody obou rodičovských rozhraní. Vícenásobná dědičnost je povolena pouze pro rozhraní.

Co je funkcionální rozhraní v Javě?

Funkcionální rozhraní — rozhraní s jednou abstraktní metodou (SAM — Single Abstract Method). Anotace @FunctionalInterface zaručuje toto omezení. Příklady: Runnable, Callable, Comparator, Consumer. Funkcionální rozhraní jsou základem lambda výrazů v Javě 8: () -> System.out.println() implementuje Runnable.

Proč jsou potřebné default metody v Java rozhraních?

Default metody umožňují přidávat nové metody do rozhraní bez změny všech implementujících tříd. Například Java 8 přidala stream() do Collection jako default metodu. Bez tohoto mechanismu by foreach(), stream() a další metody vyžadovaly změnu tisíců tříd v JDK. Default — zpětně kompatibilní způsob rozšiřování.

Jak Kotlin řeší problém vícenásobné dědičnosti?

Kotlin zakazuje vícenásobnou dědičnost tříd, ale povoluje vícenásobnou implementaci rozhraní. Pokud dvě rozhraní mají metodu se stejnou signaturou a výchozí implementací, kompilátor vyžaduje explicitní přepsání s voláním super<InterfaceName>.method(). To řeší problém diamantu na úrovni kompilace.

Shrnutí

  • Interface — kontrakt definující metody k implementaci; hlavní mechanismus polymorfismu v Javě a Kotlinu
  • Java 8+ přidala default a static metody do rozhraní, čímž zmenšila rozdíl s abstraktními třídami
  • Kotlin interfaces podporují abstraktní vlastnosti, výchozí implementace a delegování pomocí by
  • Clean Architecture používá rozhraní jako hranice mezi vrstvami Domain a Data
  • Interface Segregation Principle vyžaduje rozdělení velkých rozhraní na specializovaná
  • Funkcionální rozhraní (Single Abstract Method) — základ lambda výrazů a Stream API
  • Doporučení: přidejte rozhraní když se objeví druhá implementace nebo potřeba mocku pro testování

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také