Giao diện (interface) trong Java

1. Khái niệm interface:

Như chúng ta đã biết một lớp trong java chỉ có một siêu lớp trực tiếp hay một cha duy nhất (đơn thừa kế). Để tránh đi tính phức tạp của đa thừa kế (multi-inheritance) trong lập trình hướng đối tượng, Java thay thế bằng giao tiếp (interface). Một lớp có    thể có nhiều   giao tiếp (interface)  với các lớp khác để thừa hưởng thêm vùng dữ liệu và phương thức của các giao tiếp này.

2. Khai báo interface:

Interface được khai báo như một lớp. Nhưng các thuộc tính của interface là các hằng (khai báo dùng từ khóa final) và các phương thức của giao tiếp là trừu tượng (mặc dù không có từ khóa abstract).

Trong các lớp có cài đặt các interface ta phải tiến hành cài đặt cụ thể các phương thức này.

Ví dụ:

public interface sanpham

{ static final String nhasx = “Honda VN”;

static final String dienthoai = “08-8123456”; public int gia(String smodel);

}

// khai báo 1 lớp có cài đặt interface public class xemay implements sanpham {          // cài đặt lại phương thức của giao diện trong lớp

public int gia(String smodel)

{

if (s_model.equals(“2005”))
return (2000);

else

return (1500);

}

public String chobietnhasx()

{

}

Có   một  vấn  đề khác   với  lớp  là  một  giao  diện  (interface) không chỉ      có một  giao  diện  cha trực   tiếp  mà có  thể  dẫn  xuất cùng lúc nhiều giao diện khác (hay có nhiều giao diện cha). Khi đó nó sẽ kế thừa tất cả các giá trị hằng và các phương thức của các giao diện cha. Các giao diện cha được liệt kê thành chuỗi và cách nhau bởi dấu phẩy “,”. Khai báo như sau:

public interface InterfaceName extends interfacel, interface2, interfaces {

//…

}

3. Ví dụ minh họa

Ví dụ 1: Minh họa tính đa hình (polymorphism) trong phân cấp kế thừa thông qua việc mô tả và xử lý một số thao tác cơ bản trên các đối tượng hình học.

// Định nghĩa lớp trừu tượng cơ sở tên Shape trong

// tập tin Shape.java

public abstract class Shape extends Object {

// trả về diện tích của một đối tượng hình học shape public double area()

{

return 0.0;

}

// trả về thể tích của một đối tượng hình học shape public double volume()

{

 

// Phương thức trừu tượng cần phải được hiện thực

// trong những lớp con để trả về tên đối tượng

// hình học shape thích hợp public abstract String getName();

} // end class Shape

// Định nghĩa lớp Point trong tập tin Point.java public class Point extends Shape {

protected int x, y; // Tọa độ x, y của 1 điểm

// constructor không tham số. public Point()

{

setPoint( 0, 0 );

} // constructor có tham số.

public Point(int xCoordinate, int yCoordinate)

{

setPoint( xCoordinate, yCoordinate );

}

// gán tọa độ x, y cho 1 điểm

public void setPoint( int xCoordinate, int yCoordinate ) {

x = xCoordinate; y = yCoordinate;

}

// lấy tọa độ x của 1 điểm public int getX()

{

// lấy tọa độ y của 1 điểm public int getY()

{

return y;

}

// Thể hiện tọa độ của 1 điểm dưới dạng chuỗi public String toString()

{

return “[” + x + “, ” + y + “]”;

}

// trả về tên của đối tượng shape public String getName()

{

return “Point”;

}

} // end class Point

Định nghĩa một lớp cha Shape là một lớp trừu tượng dẫn xuất từ Object và có 3 phương thức khai báo dùng tiền tố public. Phương thức getName() khai báo trừu tượng vì vậy nó phải được hiện thực trong các lớp con. Phương thức area() (tính diện tích) và phương thức volume() (tính thể tích) được định nghĩa và trả về 0.0. Những phương thức này sẽ được khai báo chồng trong các lớp con để thực hiện chức năng tính diện tích cũng như thể tích phù hợp với những đối tượng hình học tương ứng (đường tròn, hình trụ, …)

Lớp Point: dẫn xuất từ lớp Shape. Một điểm thì có diện tích và thể tích là 0.0, vì vậy những phương thức area() và volume() của lớp cha không cần khai báo chồng trong lớp Point, chúng được thừa kế như đã định nghĩa trong lớp trừu tượng Shape. Những phương thức khác như setPoint(…) để

gán tọa độ x, y cho một điểm, còn phương thức getX(), getY() trả về tọa độ x, y của một điểm. Phương thức getName() là hiện thực cho         phương       thức     trừu     tượng       trong lớp     cha,      nếu      như phương thức getName() mà không được định nghĩa thì lớp Point là một lớp trừu tượng.

// Định nghĩa lớp Circle trong tập tin Circle.java public class Circle extends Point {   // Dẫn xuất từ lớpPoint protected double radius;

// constructor không tham số public Circle()

{

// ngầm gọi đến constructor của lớp cha setRadius( 0 );

} // constructor có tham số

public Circle( double circleRadius, int xCoordinate, int yCoordinate )

{

// gọi constructorcủa lớp cha super( xCoordinate, yCoordinate );

setRadius( circleRadius );

}

// Gán bán kính của đường tròn

public void setRadius( double circleRadius )

{

radius = (circleRadius >= 0 ? circleRadius:0);

}

// Lấy bán kính của đường tròn public double getRadius()

{

return radius;

}

// Tính diện tích đường tròn Circle public double area()

{

return Math.PI * radius * radius;

}

// Biểu diễn đường tròn bằng một chuỗi public String toString()

{

return “Center = ” + super. toString() +

“; Radius = ” + radius;

}

// trả về tên của shape public String getName()

{

return “Circle”;

}

} // end class Circle

Lớp Circle dẫn xuất từ lớp Point, một đường tròn có thể tích là 0.0, vì vậy phương thức volume() của lớp cha không khai báo chồng, nó sẽ thừa kế từ lớp Point, mà lớp Point thì thừa kế từ lớp Shape. Diện tích đường tròn khác với một điểm, vì vậy phương thức tính diện tích area() được khai báo chồng. Phương thức getName() hiện thực phương thức trừu tượng đã khai báo trong lớp cha, nếu phương thức getName() không khai báo trong lớp Circle thì nó sẽ kế   thừa từ  lớp Point. Phương thức setRadius dùng để gán một bán kính (radius) mới cho một đối tượng đường tròn, còn phương thức getRadius trả về bán kính của một đối tượng đường tròn.

// Định nghĩa lớp hình trụ Cylinder // trong tập tin Cylinder.java. public class Cylinder extends Circle {

// chiều cao của Cylinder protected double height;

// constructor không có tham số public Cylinder()

{

// ngầm gọi đến constructor của lớp cha setHeight( 0 );

}

// constructor có tham số public Cylinder( double cylinderHeight, double cylinderRadius, int xCoordinate, int yCoordinate )

{

// Gọi constructor của lớp cha super( cylinderRadius, xCoordinate, yCoordinate );

setHeight( cylinderHeight);

}

// Gán chiều cao cho Cylinder

public void setHeight( double cylinderHeight)

{

height = (cylinderHeight >= 0 ? cylinderHeight :0 );

// Lấy chiều cao của Cylinder public double getHeight()

{

return height;

}

// Tính diện tích xung quanh của Cylinder public double area()

{

return 2 * super.area() + 2 * Math.PI * radius * height;

}

// Tính thể tích của Cylinder public double volume()

{

return super.area() * height;

}

// Biểu diễn Cylinder bằng một chuỗi public String toString()

{

return super. toString() + “; Height = ” + height;

}

// trả về tên của shape public String getName()

{

return “Cylinder”;

}

} // end class Cylinder

Lớp Cylinder dẫn xuất từ lớp Circle. Một Cylinder (hình trụ) có diện tích và thể tích khác với một Circle (hình tròn), vì vậy cả hai phương thức area() và volume() cần phải khai báo chồng. Phương thức getName() là hiện thực phương thức trừu tượng trong lớp cha, nếu phương thức getName() không khai báo trong lớp Cylinder thì nó sẽ kế thừa từ lớp Circle. Phương thức setHeight dùng để gán chiều cao mới cho một đối tượng hình trụ, còn phương thức getHeight trả về chiều cao của một đối tượng hình trụ.

// Test.java

// Kiểm tra tính kế thừa của Point, Circle, Cylinder với // lớp trừu tượng Shape.

// Khai báo thư viện import java. text.DecimalFormat; public class Test {

// Kiểm tra tính kế thừa của các đối tượng hình học public static void main( String args[] )

{

// Tạo ra các đối tượng hìnhhọc Point point = new Point( 7, 11 );

Circle circle = new Circle( 3.5, 22, 8);

Cylinder cylinder = new Cylinder( 10, 3.3, 10, 10);

// Tạo một mảng các đối tượng hình học Shape arrayOfShapes[] = new Shape[ 3 ];

// arrayOfShapes[ 0 ] là một đối tượng Point arrayOfShapes[ 0 ] = point;

// arrayOfShapes[ 1 ] là một đối tượng Circle arrayOfShapes[ 1 ] = circle;

// arrayOfShapes[ 2 ] là một đối tượng cylinder arrayOfShapes[ 2 ] = cylinder;

// Lấy tên và biểu diễn của mỗi đối tượng hình học

String output =

point.getName() +        ” + point.toString() + “\n” +

circle.getName() + “: ” + circle.toString() + “\n” + cylinder.getName() + “: ” + cylinder.toString();

DecimalFormat precision2 = new DecimalFormat( “0.00” );

// duyệt mảng arrayOfShapes lấy tên, diện tích, thể tích // của mỗi đối tượng hình học trong mảng. for (int i = 0; i < arrayOfShapes.length; i+ + )

{

output + = “\n\n” + arrayOfShapes[ i ].getName() + “: ” + arrayOfShapes[ i]. toString() +

“\n Area = ” +

precision2.format( arrayOfShapes[ i ].area() ) + “\nVolume = ” +

precision2.format( arrayOfShapes[ i ].volume() );

}

System. out.println(output);

System.exit( 0 );

}

} // end class Test

Kết quả thực thi chương trình: