Các câu hỏi hay gặp khi học OOP
Java
164
oop
19
White

DAN3002 viết ngày 04/01/2019

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 đã:

  1. 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.
  2. 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ì 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à 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
  • Bạn muốn chia sẻ đoạn code trùng nhau với các class liên quan.
  • Bạn thấy các Class con có nhiều method , field giống nhau.
  • Bạn không cần sử dụng cơ chế multiple inheritance.
  • Các class không liên quan với nhau.
  • Bạn muốn tận dụng cơ thế multiple inheritance.

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:

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 ? :smile: 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ì :smile: Đây là một đặc điểm của OOP :wink:

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.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 :)

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

DAN3002

2 bài viết.
6 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
2 0
Tự học lập trình hiệu quả. Giới thiệu bản thân qua một chút, mình hiện tại đang là 1 học sinh cấp 3. Hầu hết những kiến thức lập trình mình có đượ...
DAN3002 viết hơn 1 năm trước
2 0
Bài viết liên quan
White
0 0
Clojure là ngôn ngữ functional có hỗ trợ OOP. Về mặt khoa học máy tính, có nhiều cách để thực hiện đa hình. Ở phiên bản trước 1.2, đa hình trong Cl...
Ngoc Dao viết hơn 4 năm trước
0 0
White
0 0
Trong bài viết này, một số hình ảnh hoặc nọi dung có thể bị thiếu do quá trình chế bản. Vui lòng xem nội dung ở blog gốc sau: (Link) (Link), chúng...
programmerit viết 5 năm trước
0 0
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
2 bài viết.
6 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!