Quá tải C++

Ghi đè là một tính năng cho phép một lớp con cung cấp một công cụ khai thác khả năng phát triển của phương thức đã được cung cấp bởi một trong các lớp cha của nó. Nói dễ hiểu hơn, nếu lớp con có một hoặc nhiều phương thức giống với một trong các lớp cha của nó, thì đó là ghi đè phương thức

  • Ghi đè được sử dụng để được tính đa hình khi chạy

  • Ví dụ về sử dụng Override

    • Ta sẽ xây dựng 1 cây kế thừa cho các loài động vật như hình dưới, các loài động vật này đều có chung các đặc điểm và phương thức như
      • picture – name file image đại diện cho con vật này
      • thức ăn – loại thức ăn mà con vật thích. Hiện tại, biến này chỉ có hai giá trị. cỏ (cỏ) hoặc thịt (thịt)
      • đói – một biến int biểu diễn mức độ đói của con vật. Biến này thay đổi tùy chọn khi nào con vật ăn và nó ăn bao nhiêu
      • ranh giới – các giá trị biểu tượng chiều dọc và chiều ngang (ví dụ 640 x 480) của khu vực mà các vật thể sẽ quay lại hoạt động trong đó
      • vị trí – các tọa độ X và Y của con vật trong khu vực của nó
      • makeNoise() – hành vi khi con vật phát ra tiếng kêu
      • eat() – hành động khi con vật gặp nguồn thức ăn ưa thích, thịt hoặc cỏ
      • sleep() – hành vi khi con vật được coi là đang ngủ
      • roam() – hành vi khi con vật không được ăn hay đang ngủ, có thể chỉ đi lang thang chờ đợi món gì ăn được hoặc gặp biên giới lãnh địa

    Quá tải C++

    • Tuy nhiên, các loài động vật trên lại có thức ăn và âm thanh phát ra khác nhau, vì vậy chúng ta nên để eat() và makeNoise() được cài đặt chồng chéo ở từng lớp con.

      Quá tải C++

    • Ta sẽ tiếp tục phân nhóm bọt hơn cây kế thừa trên. Chó sói và chó có hàng gần nhất, cùng thuộc họ Chó (chó), chúng thường di chuyển theo đàn nên có thể sử dụng chung phương thức roam(). Mèo, hổ, sư tử cùng thuộc họ Mèo (mèo) khi di chuyển chúng thường tránh đồng loại nên có thể sử dụng chung phương thức roam(). Hà mã sẽ tiếp tục sử dụng phương thức roam() từ động vật.

      Quá tải C++

    • Vì vậy, khi cài đặt, phương thức nào được gọi?

      • Trong kế hoạch thừa xảy ra cài đặt, cái gì ở mức thấp nhất sẽ được gọi
      • Lấy ví dụ ở hình trên, lớp Sói có bốn phương thức. sleep() được kế thừa từ Animal, roam() được thừa kế từ Canine (thực tế là phiên bản overside version của Animal), và hai phương thức mà Wolf cài đặt over the Animal - makeNoise() and eat(). The method will be call as after

    Quá tải C++

  • 1. 2 Called method of layer cha

    • Có nhiều trường hợp khi cài đặt thay thế 1 hành động của lớp cha, nhưng ta lại không muốn thay thế hoàn toàn mà chỉ muốn bổ sung một số chi tiết
      • Ví dụ. Hạn chế, Lớp tài khoản đại diện cho tài khoản ngân hàng chung. Nó cung cấp phương thức rút tiền(kép) với chức năng rút tiền, phương thức này thực hiện quy trình rút tiền cơ bản. Tiền trừ số dư tài khoản (số dư). FeeBasedAccount là loại tài khoản hàng thu phí đối với mỗi lần Ngân hàng rút tiền, nghĩa là bên cạnh quy trình rút tiền cơ bản, nó còn làm thêm một việc là miễn phí Rút tiền từ số dư tài khoản. Vì vậy, FeeBasedAccount cần truy cập nội dung của bản rút tiền() được cung cấp bởi Tài khoản, nhưng vẫn phải cài đặt lại vì nội dung đó không đủ dùng. Ta cũng không muốn sao chép nội dung bản rút() của Tài khoản vào bản của FeeBasedAccount. Thay vào đó, ta muốn có cách gọi phương thức rút tiền() của Tài khoản từ phiên bản cài đặt chồng chéo tại FeeBasedAccount
      • Cách giải quyết. từ trong phiên bản cài đặt overlay ở Layer con, ta muốn gọi đến phương thức chính thức đó của Layer cha, từ khóa super cho phép gọi đến cách thành viên được thừa kế
            public class Account {
                private double balance = 0;
    
                public void deposit(double money) {
                    balance += money;
                }
    
                public void wirhDraw(double money) {
                    balance -= money;
                }
    
                public class FeeBasedAcount extends Account {
                    private double fee = 10;
    
                    public void withdraw(double money) {
                        super.wirhDraw(money);
                        balance -= fee;
                    }
                }
            }
    

    1. 3 Các quy tắc cho việc cài đặt thay thế

    • Các danh sách tham số phải trùng nhau, kiểu giá trị trả về phải tương thích
    • Phương thức override không được giảm quyền truy cập so với phiên bản của lớp cha
      • Nói cách khác, quyền truy cập mà phiên bản của lớp con cho phép phải bằng hoặc mở rộng hơn phiên bản của lớp cha. Ta không thể cài đặt bỏ qua một phương thức công khai bằng một phiên bản riêng tư. Nếu không, vấn đề xảy ra là một lời gọi phương thức đã được biên dịch chấp nhận vì tưởng là phương thức công khai nhưng đến khi nó chạy lại thì bị máy ảo từ chối vì phiên bản được gọi lại là riêng tư
    • Must is quan hệ IS-A (kế thừa)
    • Các phương thức final, static, private không thể cài đặt thay thế
    2. quá tải

    2. 1 niệm và ví dụ

    • Nạp chồng phương thức đơn giản là có một vài phương thức trùng tên nhưng khác nhau về các đối số trong cùng 1 lớp. Cài đặt phương thức cho phép ta tạo nhiều phiên bản của một phương thức, mỗi phiên bản chấp nhận một danh sách các đối số khác nhau, với mục đích tạo thuận lợi cho cuộc gọi phương thức
    • Nạp lại phương thức được sử dụng để thu được tính đa hình tại thời điểm biên dịch
    • Ví dụ
         class Calculation {
                void sum(int a, int b) {
                    System.out.println(a + b);
                }
    
                void sum(int a, int b, int c) {
                    System.out.println(a + b + c);
                }
            }
    

    2. 2 Cách tải

    2. 2. 1 Change the number of tham số

    • Ví dụ
             class Sum {
                void sum(int a, int b) {
                    System.out.println(a + b);
                }
    
                void sum(int a, int b, int c) {
                    System.out.println(a + b + c);
                }
            }
    

    2. 2. 2 Thay đổi kiểu trả về của tham số

    • Ví dụ
            class Sum {
                void sum(int a, int b) {
                    System.out.println(a + b);
                }
    
                void sum(int a, double b) {
                    System.out.println(a + b);
                }
            }
    

    2. 3 Tự động ép kiểu khi tải

    • Kiểu dữ liệu của đối số truyền vào được thay đổi sang kiểu dữ liệu khác (tự động ép kiểu) nếu giá trị của đối số đó không phù hợp với kiểu dữ liệu của tham số đã được định nghĩa
      • Ví dụ phương thức sum(int x, double y) trong ví dụ khi được truyền tham số như sau sum(10, 20) thì giá trị tham số thứ 2 được truyền vào là int sẽ tự động ép kiểu sang kiểu double
    • Quy tắc ép kiểu. Được tự động ép về kiểu dữ liệu lớn hơn và ưu tiên kiểu dữ liệu gần nhất được ép theo thứ tự sau.
      Quá tải C++
    • Theo hình trên thì kiểu byte có thể ép sang các kiểu lớn hơn nó như short, int, float, long, double nhưng nó sẽ ưu tiên kiểu ngắn. Hoặc kiểu int can ép sang kiểu float, long, double nhưng nó sẽ ưu tiên ép sang kiểu dài vì long gần nó hơn so với 2 kiểu còn lại. Ví dụ
            class Sum {
                void sum(float a, float b) {
                    System.out.println("First method will be call");
                }
    
                void sum(long a, long b) {
                    System.out.println("Second method will be call");
                }
    
                public static void main(String[] args) {
                    Sum s = new Sum();
                    s.sum(10, 20);
                }
            }
    
    • Kết quả trong ra sẽ là "Phương thức thứ hai sẽ được gọi" tức là hàm tổng thứ 2 sẽ được gọi vì tham số truyền vào là kiểu int, nó sẽ được ưu tiên ép sang kiểu lớn hơn và có giá trị gần nhất với nó.
    • Từ đó ta có thể suy ra là kiểu kép không thể tự động ép kiểu

    2. 4 Nạp phương thức khởi tạo

    • Trường hợp ta có các chức năng khởi động lại với các hoạt động khởi động giống nhau và chỉ khác nhau ở phần xử lý các kiểu đối số. Ta sẽ không muốn sao chép lại phần mã khởi động mà các hàm khởi tạo đều có
    • Cách giải quyết. ta sẽ đặt toàn bộ mã phần đó vào một trong các quá trình khởi tạo hàm. Và ta muốn hàm khởi tạo nào cũng đều gọi đến hàm khởi tạo kia để nó hoàn thành công việc khởi tạo. Để làm việc đó, ta sử dụng this() để gọi một hàm khởi động được tạo từ bên trong một hàm khởi động khác của cùng một lớp. Ví dụ
           public class Student {
               int id;
               String name;
    
               Student() {
                   System.out.println("gọi Constructor mặc định");
               }
    
               Student(int id, String name) {
                   this(); // nó được sử dụng để gọi Constructor của lớp hiện tại
                   this.id = id;
                   this.name = name;
               }
    
               void display() {
                   System.out.println(id + " " + name);
               }
    
               public static void main(String args[]) {
                   Student e1 = new Student(111, "Viet");
                   Student e2 = new Student(222, "Nam");
                   e1.display();
                   e2.display();
               }
           }
    
    • Kết quả trong ra sẽ là
      • default constructor call
      • default constructor call
      • 111 Việt
      • 222 Nam

    2. 5 Các quy tắc tải

    • Các phương thức được nạp chồng phải cùng tên nhưng khác nhau ở các tham số
    • Chúng có thể được định nghĩa giống hoặc khác kiểu dữ liệu trả về
    • Chúng có thể được định nghĩa giống hoặc khác với công cụ sửa đổi truy cập
    • Các phương thức không được gọi là quá tải nếu chúng chỉ khác nhau ở kiểu dữ liệu trả về hoặc công cụ sửa đổi truy cập
    3. Sự khác nhau giữa quá tải và ghi đèOverrideOverloadHành viThay đổi hành vi hiện tại của phương thức. Thêm hoặc mở rộng cho hành vi của phương thức. Đa hìnhThể hiện tính đa hình tại thời gian chạy. Hiện đa hình tính tại thời điểm biên dịch. Danh sách tham số Danh sách tham số phải giống nhau. Danh sách tham số có thể khác nhau. Quyền truy cập phương thức ghi đè ở lớp con phải có quyền truy cập bằng hoặc lớn hơn phương thức ghi đè ở lớp cha. Các phương thức nạp chồng có thể có quyền truy cập khác nhau. Giá trị trả vềKiểu trả về bắt buộc phải giống nhau. Các kiểu trả về có thể khác nhau. Phạm viXảy ra giữa 2 lớp có quan hệ kế thừaXảy ra trong phạm vi cùng 1 lớp. 4. Tổng kết

    Bài viết trên mình đã giới thiệu về ghi đè, quá tải và sự khác biệt giữa chúng, hi vọng sẽ giúp ích ít nhiều cho các bạn đọc bài viết này. Bài viết trên nếu thiếu xót gì mong các bạn góp ý cho mình dưới phần comment, mình sẽ chỉnh sửa lại để bài viết có nội dung tốt hơn. Cảm ơn các bạn đã đọc bài viết