Java Interfaces ගැන සම්පූර්ණ විස්තරය | Multiple Inheritance | SC Guide

Java Interfaces ගැන සම්පූර්ණ විස්තරය | Multiple Inheritance | SC Guide

Java Interfaces Unpacked: The Multiple Inheritance SC Guide

කට්ටියට කොහොමද? Java Interfaces ගැන අද අපි කතා කරමු!

හරි, කට්ටියට කොහොමද? ඔන්න අදත් මම ආවා ඔයාලට වැදගත් Java Concept එකක් ගැන කතා කරන්න. ගොඩක් අය Java ඉගෙන ගන්නකොට පොඩ්ඩක් ව්‍යාකූල වෙන තැනක් තමයි මේ Interfaces කියන එක. ඒ වගේම Multiple Inheritance ගැන කතා කරනකොටත්, Java වල ඒක කෙලින්ම කරන්න බැරි වුණාට, Interfaces වලින් ඒකට කොහොමද විසඳුම් දෙන්නේ කියන එක ගොඩක් වැදගත්.

අද අපි බලමු Interfaces කියන්නේ මොනවද, ඒවා Java වලට කොච්චර වැදගත්ද, කොහොමද ඒවා Implement කරන්නේ, ඒ වගේම Multiple Inheritance වලට Interfaces කොහොමද අපිට උදව් කරන්නේ කියලා සරලව, ලංකාවේ අපිට තේරෙන භාෂාවෙන්.

Interface එකක් කියන්නේ මොකක්ද? (What is an Interface?)

හරි, මුලින්ම බලමු මේ Interface එකක් කියන්නේ මොකක්ද කියලා. සරලවම කිව්වොත්, Interface එකක් කියන්නේ "contract" එකක් වගේ දෙයක්. ඒ කියන්නේ, කෙනෙක් මගේ Interface එක Use කරනවා නම්, මේ මේ දේවල් අනිවාර්යයෙන්ම කරන්න ඕනේ කියලා කියන Blueprint එකක්.

උදාහරණයක් විදියට හිතන්නකෝ, අපිට "வாகனம்" (Vehicle) කියන Interface එකක් තියෙනවා කියලා. මේ වාහන හැම එකකටම start(), stop(), accelerate() වගේ පොදු behaviors තියෙන්න ඕනේ කියලා අපිට මේ Interface එකෙන් define කරන්න පුළුවන්. හැබැයි, ඒ behaviors කොහොමද implement කරන්නේ කියන එක Interface එක කියන්නේ නෑ. ඒක තීරණය කරන්නේ ඒ Interface එක Implement කරන Class එක.

සරලවම කියනවා නම්, Interface එකක් කියන්නේ 100% Abstract Class එකක් වගේ. (Java 8 වලට කලින්). මොකද, Interface එකක් ඇතුළේ Abstract Methods විතරයි තියෙන්නේ. ඒ වගේම variables තියෙනවා නම් ඒවා public static final විදියට තමයි තියෙන්නේ. ඒ කියන්නේ ඒවා constants විතරයි.

Interface එකක ප්‍රධාන අරමුණු දෙකක් තියෙනවා:

  1. Abstraction achieve කරන එක: Implementation details හංගලා, පොදු functions ටිකක් විතරක් expose කරන එක.
  2. Common behavior එකක් define කරන එක: විවිධ Classes වලට පොදු behaviors set එකක් implement කරන්න පුළුවන් contract එකක් හදන එක.

Interface එකක් Define කරන්නේ කොහොමද? (How to Define an Interface?)

Interface එකක් Define කරන එක හරිම ලේසියි. අපි interface keyword එක Use කරනවා.

මෙන්න පොඩි Code Example එකක්:

public interface Drivable {
    // Interface Methods are implicitly public and abstract (before Java 8)
    void start();
    void stop();
    void accelerate(int speed);

    // Interface Variables are implicitly public static final
    int MAX_SPEED = 200; 
}

මේ Code එක බලන්න. Drivable කියන Interface එකේ start(), stop(), accelerate(int speed) කියන methods ටික තියෙනවා. මේ methods වලට body එකක් නෑ. ඒ වගේම MAX_SPEED කියන variable එක constant එකක් විදියට define කරලා තියෙනවා.

Java 8 වල ඉඳන් Interfaces වලට default methods සහ static methods add වුණා. Default methods වලට body එකක් තියෙන්න පුළුවන්, ඒ වගේම static methods Interface එකටම අයිති methods විදියට ක්‍රියා කරනවා. ඒ ගැනත් අපි තව පොඩ්ඩක් පස්සේ කතා කරමු.

Interface එකක් Implement කරන්නේ කොහොමද? (How to Implement an Interface?)

Interface එකක් Define කරාට වැඩක් නෑනේ, ඒක Implement කරන්නේ නැතුව. Interface එකක් Implement කරන්න අපි implements කියන keyword එක Use කරනවා.

Interface එකක් Implement කරන Class එක අනිවාර්යයෙන්ම ඒ Interface එකේ තියෙන සියලුම abstract methods වලට implementation එකක් දෙන්න ඕනේ. නැත්නම් ඒ Class එකත් abstract වෙන්න ඕනේ.

අපි කලින් හදපු Drivable Interface එක Implement කරන Car Class එකක් හදමු.

public class Car implements Drivable {

    @Override
    public void start() {
        System.out.println("Car started. Vroom vroom!");
    }

    @Override
    public void stop() {
        System.out.println("Car stopped. Engine off.");
    }

    @Override
    public void accelerate(int speed) {
        System.out.println("Car accelerating to " + speed + " km/h.");
    }

    public void drive() {
        System.out.println("Driving the car.");
    }

    public static void main(String[] args) {
        Car myCar = new Car();
        myCar.start();
        myCar.accelerate(120);
        myCar.stop();

        System.out.println("Max speed for Drivable is: " + Drivable.MAX_SPEED + " km/h");

        // Polymorphism with Interfaces
        Drivable anotherVehicle = new Car(); // 'anotherVehicle' is of type Drivable, but an instance of Car
        anotherVehicle.start();
        // anotherVehicle.drive(); // This would cause a compile-time error as 'drive()' is not in Drivable interface
    }
}

මේ Car Class එක Drivable Interface එකේ තියෙන හැම method එකක්ම Implement කරලා තියෙනවා. ඒ වගේම main method එකේදී අපි Car object එකක් හදලා, Interface methods call කරලා තියෙනවා.

අන්තිමට බලන්න, Drivable anotherVehicle = new Car(); කියන line එක. මේක තමයි Polymorphism. අපි Drivable type එකේ reference variable එකක් අරගෙන, ඒකට Car object එකක් assign කරනවා. මේකෙන් වෙන්නේ, anotherVehicle කියන object එකට Drivable Interface එකේ තියෙන methods විතරක් access කරන්න පුළුවන් වෙන එක. ඒක Car Class එකේ තියෙන drive() වගේ methods වලට access දෙන්නේ නෑ. මේකෙන් code එක තව හොඳට Abstraction කරනවා.

Multiple Inheritance සිද්ධියයි Java Interfaces (Multiple Inheritance and Java Interfaces)

හරි, මෙන්න වැදගත්ම කොටස! Java වලට Class Multiple Inheritance සපෝට් කරන්නේ නෑ කියලා ඔයාලා දන්නවා ඇති. ඒ කියන්නේ, Class එකකට එක Super Class එකකින් විතරයි Extend කරන්න පුළුවන්. මේකට හේතුව තමයි "Diamond Problem" කියන එක. ඒ කියන්නේ, Class දෙකක එකම නමින් Methods තියෙනවා නම්, Sub Class එකක් ඒ දෙකෙන්ම Inherit කරනකොට මොන method එකද Use කරන්නේ කියලා ව්‍යාකූලත්වයක් ඇති වෙන එක.

නමුත්! Interfaces වලට Multiple Inheritance සපෝට් කරනවා! ඒ කියන්නේ, Class එකකට Interfaces කිහිපයක් Implement කරන්න පුළුවන්. implements keyword එක පාවිච්චි කරලා comma separated list එකක් විදියට Interfaces කිහිපයක් දෙන්න පුළුවන්.

කොහොමද Interface එකකින් Diamond Problem එක මගහැරෙන්නේ? Interface එකක තියෙන්නේ Abstract Methods විතරක් නිසා (Java 8 වලට කලින්), ඒවාට implementation එකක් නෑ. ඉතින් Class එකක් Interfaces කිහිපයක් Implement කරනකොට, ඒ methods වලට implementation එකක් දෙන්න ඕනේ ඒ Class එක විසින්ම. ඒ නිසා Diamond Problem එක එන්නේ නෑ.

උදාහරණයක් විදියට, අපිට Drivable Interface එකයි, Maintainable Interface එකයි තියෙනවා කියලා හිතමු.

public interface Maintainable {
    void checkOil();
    void serviceVehicle();
}

දැන් අපේ Car Class එකට Drivable සහ Maintainable කියන Interfaces දෙකම Implement කරන්න පුළුවන්:

public class Car implements Drivable, Maintainable {

    @Override
    public void start() {
        System.out.println("Car started. Vroom vroom!");
    }

    @Override
    public void stop() {
        System.out.println("Car stopped. Engine off.");
    }

    @Override
    public void accelerate(int speed) {
        System.out.println("Car accelerating to " + speed + " km/h.");
    }

    @Override
    public void checkOil() {
        System.out.println("Checking car oil level.");
    }

    @Override
    public void serviceVehicle() {
        System.out.println("Servicing the car.");
    }

    public static void main(String[] args) {
        Car myCar = new Car();
        myCar.start();
        myCar.accelerate(100);
        myCar.checkOil();
        myCar.serviceVehicle();
        myCar.stop();

        // You can now treat Car as both Drivable and Maintainable
        Drivable vehicle1 = myCar;
        Maintainable vehicle2 = myCar;

        vehicle1.start();
        vehicle2.checkOil();
    }
}

දැන් බලන්න! Car Class එකට Interfaces දෙකේම behaviors ලැබිලා තියෙනවා. මේක තමයි Multiple Inheritance of Type. ඒ කියන්නේ, Class එකකට එක Super Class එකකින් විතරක් Implementation Inherit කරන්න පුළුවන් වුණාට, Interfaces කීපයකින් behaviors define කරගන්න පුළුවන්. මේකෙන් අපේ code එක ගොඩක් Flexible වෙනවා.

Java 8 Default Methods ගැන පොඩි සටහනක්: Java 8 වලදී Interfaces වලට default methods ආවා. ඒ කියන්නේ Interfaces වලටත් methods වලට body එකක් දෙන්න පුළුවන් වුණා. මේක නිසා Class එකක් Interfaces දෙකක් Implement කරනකොට ඒ Interfaces දෙකේම එකම Signature (නම සහ parameters) තියෙන default methods තිබුණොත් Diamond Problem එකක් එන්න පුළුවන්. හැබැයි Java මේක Handle කරනවා. Class එකට ඒ default method එක override කරන්න පුළුවන්. නැත්නම්, Super Class එකක method එකක් තියෙනවා නම් ඒකට priority දෙනවා. මේක Interface Multiple Inheritance වලට ලොකු බලපෑමක් කරන්නේ නෑ, මොකද Class එකට තවමත් තමන්ගේ Implementation එකක් දෙන්න පුළුවන් නිසා.

Interfaces වල වාසි මොනවද? (What are the Benefits of Interfaces?)

Interfaces Use කිරීමෙන් අපිට ලොකු වාසි ගොඩක් ලැබෙනවා:

  1. Abstraction: Implementation details හංගලා, පොදු functionality එකක් විතරක් expose කරන්න පුළුවන්. මේකෙන් code එක තව හොඳට organize වෙනවා.
  2. Loose Coupling: Class එකක් Interface එකක් Implement කරනකොට, ඒ Class එක Interface එකට depend වෙනවා මිසක්, වෙනත් Concrete Class එකකට depend වෙන්නේ නෑ. මේකෙන් code එකේ coupling එක අඩු වෙනවා, ඒ කියන්නේ වෙනස්කම් කරනකොට අනිත් කොටස් වලට වෙන බලපෑම අඩු වෙනවා.
  3. Polymorphism: Interface Type එකක් විදියට Object එකක් handle කරන්න පුළුවන්. මේකෙන් Flexible code එකක් හදන්න පුළුවන්. (අපි කලින් දැක්කා වගේ Drivable anotherVehicle = new Car();)
  4. Designing APIs: Libraries හදනකොට Interfaces Use කරලා API contracts define කරන්න පුළුවන්. මේකෙන් Library එක Use කරන අයට පහසුවෙන් ඒක Integrate කරගන්න පුළුවන් වෙනවා.
  5. Achieving Multiple Inheritance of Type: Java වල Class Multiple Inheritance නැති වුණාට, Interfaces වලින් මේ වගේ functionality එකක් ලබා ගන්න පුළුවන්.

අවසාන වශයෙන්… (Finally…)

හරි, අද අපි Interfaces ගැන හොඳට කතා කළා කියලා හිතනවා. Interfaces කියන්නේ Java Object-Oriented Programming (OOP) වල ඉතාම වැදගත් Concept එකක්. Abstraction, Polymorphism වගේ දේවල් එක්ක Interfaces කොහොමද වැඩ කරන්නේ කියන එක සහ Java වල Multiple Inheritance වලට Interfaces කොහොමද විසඳුම් දෙන්නේ කියන එක දැන් ඔයාලට පැහැදිලි ඇති.

මේ ගැන තව දුරටත් කියවන්න පුළුවන් Javadoc official documentation එකෙන්. පුළුවන් නම් ඔයාලත් මේ Concepts තව ටිකක් Use කරලා බලන්න. පොඩි Projects වලට Implement කරලා බලන්න. එතකොට තව හොඳට ඔලුවට යයි.

මේ Article එක ගැන ඔයාලගේ අදහස්, ප්‍රශ්න පහළින් Comment section එකේ දාගෙන යන්න. මම පුළුවන් ඉක්මනට උත්තර දෙන්නම්. එහෙනම් අදට ඇති. ඉක්මනටම තවත් වැදගත් ලිපියකින් හමුවෙමු! ගිහින් එන්නම්!

ජය වේවා!