Interface: esensya, mga kontrata sa Java at Kotlin para sa Android

May-akda: IT Sectr Nai-publish: 2026-02-18 Oras ng pagbabasa: 9 min

Interface — ay isang kontrata na tumutukoy sa isang set ng abstract na mga pamamaraan na dapat ipatupad ng isang klase. Sa Java at Kotlin, ang mga interface ay ang pangunahing mekanismo ng abstraction at polymorphism. Sa Java 8+ ang mga interface ay maaaring maglaman ng default at static na mga pamamaraan, sa Kotlin — mga default na implementasyon. Ayon sa Google Android Developers (2025), ang mga interface ay ginagamit sa 90% ng Android na mga proyekto para sa pagtukoy ng mga layer ng arkitektura — mga repositoryo, UseCase, at serbisyo.

Mga Pangunahing Punto

  • Interface — abstract na uri na tumutukoy ng mga lagda ng pamamaraan nang walang implementasyon (bago ang Java 8)
  • Implements — keyword na nag-uugnay ng klase sa interface; ang isang klase ay maaaring magpatupad ng maraming interface
  • Default method — pamamaraan na may implementasyon sa Java interface, idinagdag sa Java 8 para sa backward compatibility
  • Kotlin interface sumusuporta ng mga property na may getter at implementasyon ng pamamaraan, pinapalitan ang abstract class sa maraming sitwasyon
  • Markup interface — walang laman na interface na ginagamit bilang marka (Serializable, Cloneable, RandomAccess)

Ano ang Interface sa Java at Kotlin?

Interface — ay isang uri ng sanggunian na naglalaman ng abstract na mga pamamaraan, mga constant, at mga default na pamamaraan. Ang klase na nagpapatupad ng interface ay obligadong magbigay ng implementasyon ng lahat ng abstract na pamamaraan nito. Sa Java, ang interface ay hindi maaaring magkaroon ng estado (mga field ng instance), ang Kotlin ay sumusunod din sa paghihigpit na ito, ngunit sumusuporta ng mga property na may aksesor.

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;
    // getter at setter
}

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();
    }
    // iba pang pamamaraan
}

Repository<T> — isang generic na interface na may CRUD na mga pamamaraan. Ang default na pamamaraan count() ay nagbibigay ng default na implementasyon na maaaring override. Ang UserRepositoryImpl ay nagpapatupad ng interface, gamit ang EntityManager para sa pag-access ng datos. Ang ganitong paraan ay nagpapahintulot sa pagsubok ng layer ng datos sa pamamagitan ng mock ng interface nang walang tunay na database.

Interface vs abstract class: kailan pipili ng alin

Ang pagpili sa pagitan ng interface at abstract na klase ay nakadepende sa pagkakaroon ng karaniwang estado at mga relasyon sa pagitan ng mga uri. Tinutukoy ng interface ang isang kontrata (kung ano ang magagawa ng klase), ang abstract na klase — isang karaniwang implementasyon (kung ano ang klase).

KriteryaInterfaceAbstract Class
Estado (mga field)Static final constant lamangOo, anumang mga field
Mga ConstructorHindiOo
Maramihang pamanaOo (implements)Hindi (extends isa)
Mga modifier ng accesspublic (Java 8-), default na mga pamamaraanLahat (private, protected, public)
Kailan gagamitinKontrata para sa hindi magkakaugnay na mga klaseKaraniwang batayan para sa magkakaugnay na mga klase

Sa Clean Architecture, ang mga interface ay inilalagay sa panloob na layer (domain), at ang mga implementasyon — sa panlabas na layer (data). Ito ay nagpapahintulot sa pagsunod sa Dependency Rule: ang panlabas na layer ay nakadepende sa panloob, hindi ang kabaligtaran. Ang abstract na mga klase ay mas madalas na ginagamit para sa template na mga pamamaraan (Template Method pattern).

Interface sa Kotlin: mga property at delegado

Ang mga interface ng Kotlin ay mas flexible kaysa sa Java: maaari silang magdeklara ng abstract na mga property at magbigay ng mga implementasyon ng pamamaraan. Hindi tulad ng Java, sinusuporta ng Kotlin ang delegasyon sa pamamagitan ng keyword na by, na makabuluhang nagbabawas ng boilerplate kapag nagpapatupad ng pattern ng Delegate.

Kotlin
interface ApiService {
    val baseUrl: String  // abstract na property
    
    suspend fun fetchData(): Result>
    
    fun getEndpoint(path: String): String {
        return "$baseUrl/$path"  // default na implementasyon
    }
}

class RetrofitApiService(
    override val baseUrl: String
) : ApiService {
    private val client = Retrofit.Builder()
        .baseUrl(baseUrl)
        .build()
    
    override suspend fun fetchData(): Result> {
        // implementasyon ng kahilingan
    }
}

// Delegasyon sa pamamagitan ng 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 ay nagpapatupad ng Logger interface sa pamamagitan ng delegasyon (by). Lahat ng tawag na log() ay ire-redirect sa logger object nang hindi nagsusulat ng wrapper na mga pamamaraan. Ito ay isang halimbawa ng komposisyon na sa Java ay mangangailangan ng 5-10 linya ng boilerplate code.

Interface sa Clean Architecture Android

Clean Architecture para sa Android ay malinaw na hinahati ang aplikasyon sa mga layer. Ang mga interface ay gumaganap bilang hangganan sa pagitan ng mga layer: ang Domain ay tumutukoy sa mga interface ng repositoryo at UseCase, ang Data ay nagbibigay ng mga implementasyon. Ito ay nagpapahintulot sa pagpapalit ng mga implementasyon nang hindi binabago ang lohika ng negosyo — pangunahing bentahe kapag lumilipat mula Room patungong Firebase o mula REST patungong GraphQL.

Kotlin
// Domain layer — interface (kontrata)
interface UserRepository {
    suspend fun getUser(id: String): User
    suspend fun updateUser(user: User)
}

// Domain layer — use case (nakadepende sa interface)
class GetUserUseCase(
    private val repository: UserRepository
) {
    suspend operator fun invoke(id: String): Result {
        return runCatching { repository.getUser(id) }
    }
}

// Data layer — implementasyon
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 — interface sa domain layer. Ang GetUserUseCase ay nakadepende sa interface, hindi sa implementasyon. Ang UserRepositoryImpl sa data layer ay nagpapatupad ng interface, pinagsasama ang API at lokal na database. Ang ganitong arkitektura ay nagpapahintulot sa pagsubok ng UseCase sa mock-repositoryo nang walang konpigurasyon ng database o network.

Default at static na mga pamamaraan sa Java 8+

Ang mga default na pamamaraan ay idinagdag sa Java 8 para sa ebolusyonaryong pagpapalawak ng mga interface nang hindi lumalabag sa backward compatibility. Kung hindi ipinatupad ng ArrayList ang bagong stream() na pamamaraan na idinagdag sa Collection, ang lumang code ay patuloy na gagana. Ang mga static na pamamaraan sa mga interface ay nagsisilbi para sa mga utility na nauugnay sa interface — alternatibo sa mga utility class.

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();
    }
    
    // constant
    String CATEGORY = "transport";
}

Ang mga default na pamamaraan ay lumulutas ng diamond problem: kung ang isang klase ay nagpapatupad ng dalawang interface na may parehong default na pamamaraan, ang compiler ay nangangailangan ng eksplisitong override. Ang mga static na pamamaraan ay tinatawag sa pamamagitan ng pangalan ng interface — Vehicle.of("car"), walang instance.

Mga karaniwang pagkakamali sa pagdidisenyo ng interface

Ang mga pagkakamali sa pagdidisenyo ng interface ay humahantong sa marupok na code, kahirapan sa pagsubok, at paglabag sa SOLID. Suriin natin ang tatlong madalas na problema.

Interface Pollution — napakaraming pamamaraan sa isang interface

Ang isang interface na may 15+ pamamaraan ay lumalabag sa Interface Segregation Principle (ISP). Halimbawa — ang lumang java.util.Dictionary na may 10+ pamamaraan. Solusyon: hatiin sa maraming maliliit na interface — ReadableRepository, WritableRepository, SearchableRepository. Ang kliyente (serbisyo) ay nakadepende lamang sa mga pamamaraan na kailangan nito.

Sobra-sobrang abstraction — interface para sa bawat klase

Ang paggawa ng interface para sa bawat klase nang walang tunay na pangangailangan para sa polymorphism ay anti-pattern na Interface overkill. Palatandaan: ang interface ay may eksaktong isang implementasyon at walang plano sa proyekto na magdagdag ng alternatibo. Solusyon: magdagdag ng interface lamang kapag lumitaw ang pangalawang baryante ng implementasyon o pangangailangan para sa mock para sa mga pagsubok.

Mga Madalas Itanong

Ano ang pagkakaiba ng interface sa abstract class sa Java?

Interface ay tumutukoy lamang ng kontrata (mga lagda ng pamamaraan), hindi maaaring magkaroon ng estado, at sumusuporta ng maramihang pamana. Abstract class ay maaaring maglaman ng mga field, constructor, at ipinatupad na mga pamamaraan, ngunit ang isang klase ay maaari lamang magmana ng isang abstract na klase. Mula noong Java 8, ang mga interface ay nakakuha ng default at static na mga pamamaraan, pinaliit ang agwat.

Maaari bang magmana ng ibang interface ang isang interface?

Oo, sa Java at Kotlin ang mga interface ay sumusuporta ng pamana. public interface AdvancedRepository<T> extends Repository<T>, Pageable — isang interface na pinagsasama ang dalawang iba pa. Ang klase na nagpapatupad ng AdvancedRepository ay dapat magpatupad ng lahat ng pamamaraan ng parehong magulang na interface. Ang maramihang pamana ay pinapayagan lamang para sa mga interface.

Ano ang functional interface sa Java?

Functional interface — isang interface na may isang abstract na pamamaraan (SAM — Single Abstract Method). Ang anotasyong @FunctionalInterface ay ginagarantiyahan ang paghihigpit na ito. Mga halimbawa: Runnable, Callable, Comparator, Consumer. Ang mga functional interface ay batayan ng lambda expression sa Java 8: () -> System.out.println() ay nagpapatupad ng Runnable.

Bakit kailangan ang default na mga pamamaraan sa Java interface?

Ang mga default na pamamaraan ay nagpapahintulot sa pagdagdag ng bagong pamamaraan sa interface nang hindi binabago ang lahat ng nagpapatupad na klase. Halimbawa, idinagdag ng Java 8 ang stream() sa Collection bilang default na pamamaraan. Kung wala ang mekanismong ito, ang foreach(), stream(), at iba pang pamamaraan ay mangangailangan ng pagbabago ng libu-libong klase sa JDK. Default — isang backward compatible na paraan ng pagpapalawak.

Paano nilulutas ng Kotlin ang problema ng maramihang pamana?

Kotlin ay nagbabawal ng maramihang pamana ng mga klase, ngunit pinapayagan ang maramihang implementasyon ng mga interface. Kung ang dalawang interface ay may pamamaraan na may parehong lagda at default na implementasyon, ang compiler ay nangangailangan ng eksplisitong override na may tawag na super<InterfaceName>.method(). Ito ay lumulutas ng diamond problem sa antas ng compilation.

Buod

  • Interface — kontrata na tumutukoy ng mga pamamaraan na dapat ipatupad; pangunahing mekanismo ng polymorphism sa Java at Kotlin
  • Java 8+ ay nagdagdag ng default at static na mga pamamaraan sa mga interface, pinaliit ang agwat sa abstract na mga klase
  • Kotlin interfaces sumusuporta ng abstract na mga property, default na implementasyon, at delegasyon sa pamamagitan ng by
  • Clean Architecture ay gumagamit ng mga interface bilang hangganan sa pagitan ng Domain at Data na mga layer
  • Interface Segregation Principle ay nangangailangan ng paghahati ng malalaking interface sa espesyalisadong mga interface
  • Mga functional interface (Single Abstract Method) — batayan ng lambda expression at Stream API
  • Rekomendasyon: magdagdag ng interface kapag lumitaw ang ikalawang implementasyon o pangangailangan para sa mock sa pagsubok

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din