Các câu hỏi hay gặp khi học OOP
Các câu hỏi hay gặp khi học OOP(Java)
Xin chào mọi người. Đây là bài viết đầu tiên của mình trên Kipalog nên sẽ có nhiều lỗi sai, mong mọi người chỉ giáo. Trong quá trình mình học về OOP trong Java thì cũng có những thắc mắc, mình xin phép được tổng hợp lại một số thắc mắc thường thấy khi bắt đầu nghiên cứu về OOP.
1. Abstract class khác Interface ở chỗ nào?
Đầu tiên thì phải định nghĩa lại hai khác niệm này đã:
Abstract class
: Đây là một Class cha dùng để định nghĩa về bản chất cho các Class con. Bản chất ở đây có thể hiểu là: loại, kiểu, nhiệm vụ, thuộc tính, ... của các Class. Hiểu nôm na là người con sẽ được kế thừa các đặc tình của người cha.Interface
: Có thể hiểu đây là một dạng bảng thiết kế cho chức năng mà bất kỳ Class nào cũng có thể có. Một interface chứa các hành vi mà một class triển khai.
==> Điểm khác biệt đầu tiên có thể thấy là
Abstract
là một Class còn Interface
thì không. Một Class có thể mô tả các thuộc tính và hành vi của một Object. Còn Interface
lại chứa các hành vi mà một Class sẽ triển khai. Ngoài ra còn một số điểm khác biệt sau đây:Abstract class | Interface | |
---|---|---|
Định nghĩa code | Hỗ trợ định nghĩa cho các void, property | Không hỗ trợ định nghĩa mà chỉ cho khai báo |
Về Access Modifiers | Cho phép xác định Modifier | Mặc định đều là public |
Fields and Constants | Có hỗ trợ | Không hỗ trợ |
Đa kế thừa | Không hỗ trợ, chỉ có thể extend 1 Abstract class | Có hỗ trợ |
2. Tại sao phải chia ra Abstract và Interface?
Như đã nói ở bên trên thì
Bài toán: Bạn cần phải tạo ra một vườn thú gồm có các con vật sau: Chó, Mèo, Chim và Cá. Mỗi loài vật đều có điểm chung như có tên, tiếng kêu nhưng cũng có điểm riêng như bơi, bay, chạy.
Interface
có hỗ trợ đa kế thừa còn Abstract
thì lại không. Ngoài ra thì còn một tác dụng nữa, bạn xem ví dụ sau nha:Bài toán: Bạn cần phải tạo ra một vườn thú gồm có các con vật sau: Chó, Mèo, Chim và Cá. Mỗi loài vật đều có điểm chung như có tên, tiếng kêu nhưng cũng có điểm riêng như bơi, bay, chạy.
Vậy ta nên giải quyết vấn đề này như nào bây giờ? Chả nhẽ lại viết một Class
Animal
cha rồi ở mỗi Class con thì sẽ viết từng điểm riêng cho nó sao?public abstract class Animal
{
public String name;
public String sound;
public Animal(String name, String sound) {
this.name = name;
this.sound = sound;
}
}
public class Cat extends Animal
{
private void iRun()
{
System.out.println(name + "run");
}
public Cat(String name, String sound) {
super(name, sound);
}
}
...
Vậy thì dài quá :( Nhưng chúng ta hãy phân tích lại nhé :) Mỗi loài vật đều có những điểm chung cố định, vậy nên chúng ta sẽ cho nó vào 1 Abstract class. Còn các điểm riêng thì sao? Đây chính là lúc mà
Chốt lại, bạn nên xác định rõ dùng
Interface
phát huy tác dụng, nó dùng các chức năng mà :) Nên chúng ta có thể sử dụng chúng để thiết kế cho từng chức năng Chạy, Bơi, Bay, ... Rồi implements
cho từng Class riêng biệt. Điều này cũng có thể giải quyết cho những loài vật có nhiều khả năng như cả chạy cả bay.Chốt lại, bạn nên xác định rõ dùng
Abstract
hay Interface
qua các điều kiện sau đây:Abstract class | Interface |
---|---|
|
|
3. Tại sao nên khai báo <Lớp cha> = new <Lớp con>
Điều này được gọi là tính Đa Hình trong OOP.
Ví dụ ta có 1 Class Shape là class cha và 2 Class HinhTamGiac, HinhVuong là class con như sau:
Ví dụ ta có 1 Class Shape là class cha và 2 Class HinhTamGiac, HinhVuong là class con như sau:
public abstract class Shape
{
public abstract int tinhChuVi();
public abstract void veHinh();
}
public class HinhTamGiac extends Shape
{
@Override
public int tinhChuVi()
{
return 1;
// Ở đây chỉ là ví dụ thôi
}
@Override
public void veHinh()
{
System.out.println("Tam Giac");
}
}
public class HinhVuong extends Shape
{
@Override
public int tinhChuVi() {
return 2;
}
@Override
public void veHinh() {
System.out.println("Hinh Vuong");
}
}
Có phải nó rất dài không, tại sao lại phải viết thêm Class cha mà sao không viết hẳn luôn 2 class con ra ? Nhưng nếu bây giờ ta có một Class Controller nữa:
public class Controller
{
public static void main(String[] args)
{
Shape[] list = new Shape[2];
list[0] = new HinhTamGiac();
list[1] = new HinhVuong();
for(Shape shape : list)
{
printInfo(shape);
}
}
public static void printInfo(Shape shape)
{
System.out.println("Chu vi: " + shape.tinhChuVi());
shape.veHinh();
}
}
Nếu trong trường hợp này, bạn viết riêng 2 Class con ra thì tức là bạn sẽ phải viết từng void printInfo cho từng Class cụ thể. Đồng thời cùng phải tạo ra hai Array riêng để chứa từng loại ==> Quá dài dòng và phức tạp đúng không ?? Điều này rất bất tiện, mỗi khi có kiểu Shape mới bạn lại phải vào sửa, thêm phương thức trong Controller.java ==> Mất thời gian.
==> Chốt lại: Tính đa hình giúp cho các Class chỉ cần quan tâm đến đối tượng mình đang làm việc có thể làm được gì, chứ không quan tâm đó là cái gì Đây là một đặc điểm của OOP
==> Chốt lại: Tính đa hình giúp cho các Class chỉ cần quan tâm đến đối tượng mình đang làm việc có thể làm được gì, chứ không quan tâm đó là cái gì Đây là một đặc điểm của OOP
4. Có thể khai báo <Lớp con> = new <Lớp cha>
được không?
Câu trả lời là không được :) Vì khi khai báo
<Lớp con> = new <Lớp cha>
tức là bạn đang tạo một Object <Lớp con>
và chứa nó trong <Lớp cha>
. Lớp con sẽ nhiều thuộc tính/phương thức hơn so với lớp cha.Nếu khai báo dữ liệu kiểu con thì cần điền đủ dữ liệu cho nó, nhưng bạn lại new lớp cha, có dữ liệu ít (không đủ).
Vẫn có trường hợp lớp con chỉ kế thừa mà không thêm thắt gì cả. Nhưng để đảm bảo tính “mở rộng” thì
<Lớp con> = new <Lớp cha>
không được phép.5. Upcasting và Downcasting là gì?
Đây là 2 cơ chế ép kiểu sử dụng phổ biến cho các loại biến tham chiếu.
1.
1.
Upcasting
: Đây là cơ chế để bạn chuyển từ đối tượng Class con sang đối tượng là Class cha. Chú ý là lúc này đối tượng đó sẽ không dùng được các method của Class con nữa. Và nó cũng khác với việc khai báo <Lớp con> = new <Lớp cha>
.Cat cat = new Cat();
Animal animal2 = (Animal) cat; // Upcasting
2.
Downcasting
: Ngược lại thì đây là cơ chế để bạn chuyển từ đối tượng Class cha sang đối tượng là Class con. Chú ý là bạn chỉ có thể Downcasting
các Object được khai báo kiểu <Lớp cha> = new <Lớp con>
vì khi đó thì mới có thể chứa được Object mới. Cơ chế này thường được sử dụng khi bạn khai báo tính đa hình và muốn sử dụng các method, ... từ Class con.Animal animal = new Cat();
Cat cat = (Cat) animal;
Cảm ơn các bạn đã đọc hết bài viết này :) Hy vọng các bạn ủng hộ và góp ý để mình viết các bài sau tốt hơn :)