Java – Interface

Interface là một trong những khái niệm cốt lõi trong Java. Java Interface là phần cốt lõi của ngôn ngữ lập trình Java và không những được sử dụng nhiều trong SDK mà còn cả trong các design pattern. Hầu hết các framework sử dụng java interface rất nhiều.

Interface trong Java cung cấp cách thực hiện abstraction. Java interface cũng được sử dụng để định nghĩa giao kèo cho các subclass để implement.

Ví dụ chúng ta muốn tạo một bản vẽ bao gồm nhiều hình dạng. Ở đây chúng ta có thể tạo một interface gọi là Shape và định nghĩa tất cả các phương thức mà các loại Shape object khác nhau sẽ implement. Để đơn giản hơn, chúng ta chỉ tạo 2 phương thức: draw() để vẻ hình dạng và getArea() trả về bề mặt của hình dạng.

Shape.java

package com.example.design;

public interface Shape {
  // public, static và final
  public String LABLE= "Shape";
	
  // các phương thức interface là abstract và public
  void draw();
	
  double getArea();
}

Những điểm quan trọng về inteface trong Java

  1. Từ khoá interface được dùng để tạo một interface trong Java
  2. Chúng ta không thể khởi tạo một interface trong Java
  3. Interface cung cấp abstraction tuyệt đối, abstract class cũng cung cấp abstraction nhưng abstract class có thể cung cấp các phương thức đã được implement trong khi interface thì không thể
  4. Interface không thể có constructor bởi vì chúng ta không thể khởi tạo chúng và các phương thức trong interface sẽ không có body
  5. Mặc định thì bất kỳ thuộc tính nào của interface đều ngầm là public, staticfinal, nên chúng ta không cần cung cấp access modifier cho các thuộc tính, nhưng nếu làm thì trình biên dịch cũng sẽ không cảnh bảo về điều này
  6. Mặc định các phương thức interface ngầm là publicabstract. Nó hoàn toàn có ý nghĩa bởi vì tất cả các phương thức trong interface đều chưa được implement và do đó các subclass sẽ cung cấp implement cho các phương thức này.
  7. Interface không thể extends bất kỳ class nào nhưng nó có thể extends các interface khác. public interface Shape extends Cloneable{} là ví dụ một interface extends interface khác. Ngoài ra thì Java cung nhiều kế thừa trong interface, nghĩa là một interface có thể extends nhiều interface khác.
  8. Từ khoá implements được sử dụng bởi class để định nghĩa implement cho một interface.
  9. Một class implement một interface thì nó phải cung cấp thực thi cho tất cả các phương thức trừ khi nó là abstract class. Ví dụ chúng ta có thể cung cấp thực thi cho interface bên trên trong abstract class như sau

ShapeAbs.java

package com.example.design;

public abstract class ShapeAbs implements Shape {
  @Override
  public double getArea() { 
    // TODO Auto-generated method stub
    return 0;
  }
}

10. Chúng ta luôn cố gắng viết chương trình trong giới hạn của interface thay vì quan tâm các thực thi nên chúng ta biết trước rằng các class thực thi sẽ luôn cung cấp các thực thi và trong tương lại nếu có cách thực thi nào tốt hơn, chúng ta sẽ chuyển sang dễ dàng hơn.

Implementation của interface

Nào chúng ta hãy cũng xây dựng các class implementation của interface

Circle.java

package com.example.design;

public class Circle implements Shape{

  private double radius;

  public Circle(double r){
    this.radius = r;
  }
	
  @Override
  public void draw(){
    System.out.println("Drawing Circle");
  }
	
  @Override
  public double getArea(){
    return Math.PI*this.radius*this.radius;
  }

  public double getRadius(){
    return this.radius;
  }
}

Class Circle đã thực thi tất cả các phương thức định nghĩa trong interface và nó cũng có một vài phương thức riêng như là getRadius(). Implementation của interface có thể có nhiều kiểu constructor. Hãy cùng xem implementation khác sau

Rectangle.java

package com.example.design;

public class Rectangle implements Shape {

  private double width;
  private double height;
	
  public Rectangle(double w, double h){
    this.width=w;
    this.height=h;
  }

  @Override
  public void draw() {
    System.out.println("Drawing Rectangle");
  }

  @Override
  public double getArea() {
    return this.height*this.width;
  }
}

Dưới đây là test code để giúp cho chúng ta hiểu và chạy thử các class bên trên

package com.example.design;

public class ShapeTest {

  public static void main(String[] args) {
		
    //programming for interfaces not implementation
    Shape shape = new Circle(10);
		
    shape.draw();
    System.out.println("Area=" + shape.getArea());
		
    //switching from one implementation to another easily
    shape = new Rectangle(10,10);
    shape.draw();
    System.out.println("Area=" + shape.getArea());
  }
}

Kết quả

Drawing Circle
Area=314.1592653589793
Drawing Rectangle
Area=100.0

Ưu điểm

  1. Interface cung cấp giao kèo cho tất cả các subclass thực thi, nên nó rất tốt cho việc code theo điều kiện của interface bởi vì các class thực thi sẽ không thể bỏ qua các phương thức đang sử dụng trong interface.
  2. Interface rất tốt như là điểm khởi đầu để định nghĩa Type và tạo hệ thống phân cấp cao nhất trong code.
  3. Do Java class có thể implements nhiều interface, nên tốt hơn hết là coi interface như là một super class trong hầu hết các trường hợp.

Nhược điểm

Mặc dù interface có nhiều ưu điểm nhưng nó cũng có những nhược điểm như sau

  1. Chúng ta cần lựa chọn các phương thức interface hết sức cẩn thận khi thiết kế dự án của mình bởi vì chúng ta không thể thêm hay xoá bất kỳ phương thức nào của interface sau đấy, nó sẽ dẫn đến lỗi biên dịch cho tất cả các class thực thi mà dựa trên interface trong code của chúng ta, nguyên nhân gây nên việc khó khăn cho việc maitain code.
  2. Nếu các class thực thi có các phương thức của riêng nó, chúng ta không thể sử dụng code trực tiếp bởi vì kiểu của object là một interface không có những phương thức đó. Ví dụ như đoạn code bên trên sẽ bị biên dịch lỗi khi chúng ta gọi shape.getRadius(). Để khắc phục lỗi này, chúng ta có thể sử dụng typecasting và sử dụng phương thức như sau
Circle c = (Circle) shape;
c.getRadius();

Cho dù class typecasting cũng có những nhược điểm

Java 8

Các thay đổi Interface trong Java 8 bao gồm các phương thức static và default. Trước Java 8, chúng ta có thể chỉ có khai báo các phương thức trong interface. Nhưng từ Java 8 trở đi chúng ta bắt đầu có phương thức static và default.

Phương thức default

Để tạo phương thức default thì chúng ta sử dụng từ khoá default

package com.example.java8.defaultmethod;

public interface Interface1 {

  void method1(String str);
	
    default void log(String str){
      System.out.println("I1 logging::"+str);
    }
}

log(String str) là phương thức mặc định, nên khi một class extend Interface1, nó sẽ không cần phải cung cấp thực thi cho phương thức này.

Chúng ta biết rằng trong Java, chúng ta không thể thực hiện extends nhiều class do gặp phải vấn đề “Diamon problem”, do trình biên dịch sẽ không thể quyết định phương thức của super class sử dụng. Nên với trường hợp phương thức default của interface chúng ta cũng sẽ gặp vấn đề tương tự bởi vì khi class extends từ nhiều interface, khi cùng chứa phương thức default, trình biên dịch sẽ rất khó quyết định sử dụng phương thức của interface nào. Để tránh việc này xảy ra thì Java bắt buộc chúng ta phải cung cấp implement cho các phương thức default tồn tại ở nhiều interface trong class

Phương thức static

Phương thức static giống với phương thức default ngoại trừ một điểm chúng ta không thể override trong các class thực thi. Tính năng này giúp chúng ta tránh được các kết quả không mong muốn trong trường hợp các subclass thay đổi kết quả của interface. Hãy xem ví dụ sau

package com.example.java8.staticmethod;

public interface MyData {

  default void print(String str) {
    if (!isNull(str))
      System.out.println("MyData Print::" + str);
    }

  static boolean isNull(String str) {
    System.out.println("Interface Null Check");
    return str == null ? true : "".equals(str) ? true : false;
  }
}

 

You May Also Like

About the Author: Nguyen Dinh Thuc

Leave a Reply

Your email address will not be published.