Lập
trình hướng đối tượng cho phép ta tạo ra các lớp đối tượng mới từ lớp đã tồn tại
sẵn. Việc này được gọi tên là “thừa kế”.
Thừa kế
là một chức năng quan trọng và mạnh mẽ để có thể viết ra các phần chương trình
dễ dàng dùng lại được. Chẳng hạn, bạn cần định nghĩa các lớp để mô phỏng “hình
tròn”, “hình chữ nhật” và “tam giác”. Có rất nhiều thuộc tính và hành vi chung giữa
các lớp đó. Làm thế nào để viết các lớp đó mà tránh được mã lặp, cũng như dễ
nâng cấp bảo trì tất cả cùng một lúc? Câu trả lời nằm ở sự vận dụng thừa kế.
Lớp cha
và lớp con
Thừa
kế cho phép bạn định nghĩa ra một lớp đối tượng tổng quát (được gọi dưới tên “lớp
cha”), và sau đó mở rộng nó thành những lớp đặc trưng hơn (được gọi dưới tên “lớp
con”.)
Ta đã
biết rằng ta sử dụng lớp đối tượng để lên mô hình những đối tượng thuộc cùng một
loại. Trên thực tế có nhiều lớp đối tượng có các thuộc tính và hành vi tổng
quát, những thứ được chia sẻ chung nhau giữa nhiều lớp đối tượng. Bạn có thể định
ra một lớp đối tượng đặc thù dành cho những thuộc tính tổng quan ấy, và tạo ra
các lớp khác mà ngoài việc thừa kế những đặc trưng của lớp cha, còn có những đặc
tính mở rộng của riêng chúng.
Hãy xem
xét các hình của hình học phẳng, trong tình huống bạn đang xây dựng một ứng dụng
cần tới chức năng vẽ hình. Dù gì đi nữa, tất cả các hình vẽ đều có những thuộc
tính chung nhau, chúng đều được vẽ viền bởi một màu nào đó và được đổ đầy (hoặc
không) bởi một màu nào đó. Bởi vậy mà một lớp tổng quát, Geometric, có thể được dùng để lên mô hình cho mọi đối tượng hình
hình học, lớp này chứa thuộc tính color và filled và những getter và setter liên quan. Thế là ta có thể làm ra những lớp Cirle cũng như Rectangle
mà kế thừa những phương thức và thuộc tính đó. Hình dưới đây mô phỏng mối quan
hệ giữa các lớp trên. Để ý mũi tên chỉ ra mối quan hệ thừa kế giữa hai lớp đối
tượng.
Hãy xem
xét từng dữ kiện một, sau đó chúng ta bắt đầu viết mã triển khai sơ đồ. Lưu ý rằng
mã triển khai dưới đây có các dòng comment bằng tiếng Việt được thêm vào như một
phần của bài đọc, không phải là một phần của mã lệnh.
Geometric.java
public class Geometric {
/* các trường dữ liệu */
private
String color = "white";
private
String filled = null;
/* các khởi tạo tử */
public Geometric() {
}
public Geometric(String color, String filled) {
this.color
= color;
this.filled
= filled;
}
/* các thuộc tính */
public
String getColor() {
return
color;
}
public void setColor(String color) {
this.color
= color;
}
public
String getFilled() {
return
filled;
}
public void setFilled(String filled) {
this.filled
= filled;
}
public
String toString() {
return "created with \"" + color + "\" color and " +
(filled == null ? "no
fill" : "filled with \"" + filled + "\" color");
}
}
Circle.java
Để
thông báo rằng lớp Circle (thừa kế và) mở rộng lớp Geometric, ta sử dụng từ khóa extends như
dưới đây:
public class Circle extends Geometric {
/* mở rộng trường dữ liệu của lớp cha */
private double radius;
public Circle() {
}
public Circle(double radius) {
this.radius
= radius;
}
public Circle(double radius, String color, String filled) {
this.radius
= radius;
setColor(color);
setFilled(filled);
}
public double getRadius() {
return
radius;
}
public void setRadius(double
radius) {
this.radius
= radius;
}
public double getArea() {
return
radius * radius * Math.PI;
}
public double getPerimeter() {
return 2 * radius * Math.PI;
}
public double getDiameter() {
return 2 * radius;
}
public void printCircle() {
System.out.println("The " + getColor() + " circle is created with the
radius is " +
radius);
}
}
Nhờ thừa
kế, lớp Circle được thừa hưởng những phương thức getColor, setColor, getFilled, setFilled, và toString.
Khởi tạo
tử chồng Circle(double
radius, String color, String filled) được triển khai bằng cách gọi phương thức setColor và setFilled để cài đặt các thuộc tính color và filled.
Thử
để thấy rằng bạn không thể cài đặt color
và filled bằng cách sử dụng trực tiếp như sau:
public Circle(double radius, String color, String filled) {
this.radius
= radius;
this.color
= color;
this.filled
= filled;
}
Đó là
vì dữ liệu private của lớp Geometric
không thể được truy xuất từ bất kỳ lớp nào ngoại trừ bản thân lớp Geometric, cách duy nhất để đọc và sửa color và filled là thông qua những phương thức getter
và setter của chúng.
Rectangle.java
Tương tự
như Circle, chúng ta viết mã triển khai cho lớp Rectangle:
public class Rectangle extends Geometric {
private double width;
private double height;
public Rectangle() {
}
public Rectangle(double width, double
height) {
this.width
= width;
this.height
= height;
}
public Rectangle(String color, String filled, double width, double height) {
this.width
= width;
this.height
= height;
setColor(color);
setFilled(filled);
}
public double getWidth() {
return
width;
}
public void setWidth(double
width) {
this.width
= width;
}
public double getHeight() {
return
height;
}
public void setHeight(double
height) {
this.height
= height;
}
public double getArea() {
return
width * height;
}
public double getPerimeter() {
return 2 * (width + height);
}
}
Sử dụng các lớp đã tạo trên
Mã dưới
đây tạo ra những đối tượng của lớp Circle cũng
như Rectangle và gọi những phương thức của hai lớp
đó. Để ý rằng phương thức toString được cả hai class này thừa hưởng và ta
có thể gọi phương thức đó từ những đối tượng của cả hai phương thức.
public class TestCircleRectangle {
public static void main(String[]
args) {
Circle circle = new Circle(1);
circle.setFilled("black");
System.out.println("A circle " + circle.toString());
System.out.println("The radius is " + circle.getRadius());
System.out.println("The radius is " + circle.getRadius());
System.out.println("The area is " + circle.getArea());
System.out.println("The diameter is " + circle.getDiameter());
System.out.println();
Rectangle rectangle = new Rectangle(2, 4);
System.out.println("A rectangle " + rectangle.toString());
System.out.println("The area is " + rectangle.getArea());
System.out.println("The perimeter is " + rectangle.getPerimeter());
System.out.println();
}
}
Kết quả:
A
circle created with "white" color and filled with "black" color
The
radius is 1.0
The
radius is 1.0
The
area is 3.141592653589793
The
diameter is 2.0
A
rectangle created with "white" color and no fill
The
area is 8.0
The
perimeter is 12.0
Đăng nhận xét