Bài tập java về phân số hỗn số năm 2024

Kế thừa trong Java là một trong những khái niệm cơ bản và quan trọng trong lập trình hướng đối tượng giúp tăng tính tái sử dụng mã nguồn và tránh lặp lại code. Trong bài viết này, hãy cùng Rikkei Academy tìm hiểu chi tiết về khái niệm này nhé!

Kế thừa trong Java là gì?

Kế thừa (inheritance) trong Java là một tính năng của lập trình hướng đối tượng, cho phép một lớp (class) mới tiếp nhận các thuộc tính và phương thức của một lớp khác. Lớp mới được gọi là lớp con (subclass), và lớp mà nó kế thừa được gọi là lớp cha (superclass). Kế thừa giúp tái sử dụng mã nguồn, giảm độ lặp lại và tăng tính mô-đun của chương trình.

Các thuật ngữ quan trọng trong kế thừa Java:

  • Lớp cha (Superclass): Lớp mà các thuộc tính và phương thức được kế thừa bởi lớp con.
  • Lớp con (Subclass): Lớp kế thừa các thuộc tính và phương thức từ lớp cha.
  • extends: Từ khóa dùng để chỉ rõ lớp con kế thừa từ lớp cha.
  • super: Từ khóa dùng để truy cập các thuộc tính và phương thức của lớp cha từ lớp con.

Khi nào cần sử dụng kế thừa trong Java?

Các trường hợp thường sử dụng kế thừa trong Java bao gồm:

  • Khi có một số lớp có các thuộc tính và phương thức chung bằng cách tạo ra một lớp cha chung và kế thừa từ lớp đó để tránh lặp lại mã.
  • Khi cần mở rộng các chức năng của một lớp hiện có bằng cách thêm các thuộc tính và phương thức mới.
  • Khi cần ghi đè phương thức của lớp cha để đạt được hành vi khác nhau trong lớp con.
  • Khi cần tạo ra một số lớp khác nhau với các thuộc tính và phương thức chung bằng cách tạo ra một lớp cha chung và kế thừa từ lớp đó để tạo ra các lớp con khác nhau.

Cú pháp kế thừa trong Java

Trong Java, để thực hiện kế thừa, bạn sử dụng từ khóa extends. Cú pháp chung của kế thừa trong Java như sau:

class Subclass extends Superclass {

// Code của lớp con

}

Phân loại tính kế thừa trong Java

Trong Java, kế thừa có thể được chia làm 5 loại:

  • Đơn kế thừa
  • Kế thừa đa cấp
  • Kế thừa phân cấp
  • Đa kế thừa
  • Kế thừa hỗn hợp

Đơn kế thừa (Single inheritance)

Đơn kế thừa được sử dụng khi ta muốn tạo ra một lớp con duy nhất, kế thừa từ một lớp cha duy nhất. Điều này giúp cho mã nguồn dễ hiểu và dễ bảo trì hơn, bởi vì mối quan hệ giữa các lớp con và lớp cha là rõ ràng và dễ đoán.

Tuy nhiên, đơn kế thừa cũng có nhược điểm, đó là ta không thể kế thừa các thuộc tính và phương thức của nhiều lớp cha khác nhau. Điều này có thể gây khó khăn trong việc tạo ra các lớp con phức tạp và đa dạng.

class Animal {

public void eat() {

System.out.println(“Eating…”);

}

}

class Dog extends Animal {

public void bark() {

System.out.println(“Barking…”);

}

}

public class Main {

public static void main(String[] args) {

Dog d = new Dog();

d.eat(); // gọi phương thức từ lớp cha

d.bark(); // gọi phương thức từ lớp con

}

}

Kế thừa đa cấp (Multilevel inheritance)

Trong Java, kế thừa đa cấp (multilevel inheritance) được sử dụng khi ta cần tạo ra các lớp con phức tạp và đa dạng, các lớp con này có thể kế thừa các thuộc tính và phương thức từ nhiều lớp cha khác nhau.

Kế thừa đa cấp cho phép ta tạo ra một hệ thống kế thừa theo dạng đường thẳng, trong đó, một lớp được kế thừa từ một lớp cơ sở và cũng có thể đóng vai trò là lớp cơ sở cho các lớp khác.

class Animal {

public void eat() {

System.out.println(“Animal is eating”);

}

}

class Mammal extends Animal {

public void run() {

System.out.println(“Mammal is running”);

}

}

class Cat extends Mammal {

public void meow() {

System.out.println(“Cat is meowing”);

}

}

public class Main {

public static void main(String args[]) {

Cat c = new Cat();

c.eat(); // kế thừa từ lớp cha Animal

c.run(); // kế thừa từ lớp cha Mammal

c.meow(); // kế thừa từ chính lớp Cat

}

}

Kế thừa phân cấp (Hierarchical inheritance)

Trong kế thừa phân cấp, một lớp cha được kế thừa bởi nhiều lớp con khác nhau. Hệ thống kế thừa trong Hierarchical inheritance có dạng cây. So với kế thừa đa cấp, trong kế thừa phân cấp, một lớp con có thể kế thừa từ một lớp cha và cũng là lớp cha của một lớp con khác, tạo ra một cây kế thừa phức tạp hơn.

Ta sử dụng kế thừa phân cấp khi muốn tạo ra một hệ thống lớp đối tượng có sự tương quan (hierarchy) theo kiểu “is-a” (là một…).

class Animal {

public void eat() {

System.out.println(“Eating…”);

}

}

class Dog extends Animal {

public void bark() {

System.out.println(“Barking…”);

}

}

class Cat extends Animal {

public void meow() {

System.out.println(“Meowing…”);

}

}

public class Main {

public static void main(String[] args) {

Dog d = new Dog();

d.eat(); // gọi phương thức từ lớp cha

d.bark(); // gọi phương thức từ lớp con

Cat c = new Cat();

c.eat(); // gọi phương thức từ lớp cha

c.meow(); // gọi phương thức từ lớp con

}

}

Đa kế thừa (Multiple Inheritance)

Đa kế thừa (multiple inheritance) trong Java là khả năng kế thừa các tính năng từ nhiều lớp cha khác nhau vào một lớp con. Tuy nhiên, Java không hỗ trợ đa kế thừa trực tiếp. Để đạt được đa kế thừa, ta phải thông qua các Interface trong Java.

Lưu ý rằng Java không hỗ trợ đa kế thừa với các lớp.

interface Animal {

public void eat();

}

interface Vehicle {

public void start();

}

class Dog implements Animal, Vehicle {

public void eat() {

System.out.println(“Eating…”);

}

public void start() {

System.out.println(“Starting…”);

}

public void bark() {

System.out.println(“Barking…”);

}

}

public class Main {

public static void main(String[] args) {

Dog d = new Dog();

d.eat();

d.start();

d.bark();

}

}

Kế thừa hỗn hợp (Hybrid Inheritance)

Kế thừa hỗn hợp (hybrid inheritance) là sự kết hợp giữa kế thừa đa cấp (multilevel inheritance) và kế thừa đa dạng (multiple inheritance). Trong Java, kế thừa hỗn hợp chỉ được thực hiện bằng cách sử dụng interface để triển khai các tính năng từ nhiều lớp khác nhau. Ngoài ra, Java không hỗ trợ đa kế thừa với các lớp, nên kế thừa hỗn hợp cũng không thể được thực hiện bằng các lớp

Lưu ý vì kế thừa hỗn hợp là một khái niệm khá phức tạp và không nên được sử dụng quá thường xuyên.

Ví dụ:

interface Animal {

public void eat();

}

interface Vehicle {

public void start();

}

class Dog implements Animal, Vehicle {

public void eat() {

System.out.println(“Eating…”);

}

public void start() {

System.out.println(“Starting…”);

}

public void bark() {

System.out.println(“Barking…”);

}

}

class Labrador extends Dog {

public void color() {

System.out.println(“Brown”);

}

}

public class Main {

public static void main(String[] args) {

Labrador l = new Labrador();

l.eat();

l.start();

l.bark();

l.color();

}

}

Tính đa hình trong kế thừa Java

Tính đa hình là một trong những tính chất quan trọng của lập trình hướng đối tượng, nó cho phép các đối tượng cùng một lớp cha có thể có hành vi khác nhau tùy thuộc vào lớp con mà chúng kế thừa.

Tính đa hình trong Java được thể hiện thông qua kế thừa, nghĩa là các lớp con có thể thay đổi hoặc mở rộng các phương thức của lớp cha. Khi một phương thức được gọi trên một đối tượng của lớp cha, thì chương trình sẽ tự động chọn phương thức phù hợp của lớp con để thực hiện.

Ví dụ:

class Animal {

public void makeSound() {

System.out.println(“The animal makes a sound.”);

}

}

class Cat extends Animal {

public void makeSound() {

System.out.println(“Meow.”);

}

}

class Dog extends Animal {

public void makeSound() {

System.out.println(“Woof.”);

}

}

public class Main {

public static void main(String[] args) {

Animal animal1 = new Animal();

Animal animal2 = new Cat();

Animal animal3 = new Dog();

animal1.makeSound(); // In ra “The animal makes a sound.”

animal2.makeSound(); // In ra “Meow.”

animal3.makeSound(); // In ra “Woof.”

}

}

Lớp “Animal” được định nghĩa với phương thức “makeSound()”. Lớp “Cat” và “Dog” kế thừa từ lớp “Animal” và ghi đè phương thức “makeSound()” để thực hiện các hành vi khác nhau.Trong hàm main(), ta tạo ba đối tượng: “animal1” thuộc lớp “Animal”, “animal2” thuộc lớp “Cat”, và “animal3” thuộc lớp “Dog”. Ta gọi phương thức “makeSound()” của các đối tượng này tương ứng, kết quả sẽ in ra “The animal makes a sound.”, “Meow.” và “Woof.” tương ứng.

Điều này cho thấy tính đa hình trong kế thừa Java, vì các đối tượng con “Cat” và “Dog” đã ghi đè lại phương thức “makeSound()” của đối tượng cha “Animal” để thực hiện các hành vi khác nhau.

Phạm vi truy cập trong kế thừa

Trong kế thừa, phạm vi truy cập là một khái niệm quan trọng để xác định quyền truy cập của các thành phần (thuộc tính và phương thức) của lớp cha trong lớp con. Có ba loại phạm vi truy cập trong Java:

  • public: Các thành phần được khai báo với phạm vi truy cập public có thể được truy cập từ bất kỳ đâu trong chương trình.
  • protected: Các thành phần được khai báo với phạm vi truy cập protected có thể được truy cập từ bên trong lớp đó hoặc các lớp con của nó.
  • private và default: Các thành phần được khai báo với phạm vi truy cập private hoặc không có phạm vi truy cập (còn gọi là default) chỉ có thể được truy cập từ bên trong lớp đó.

Khi một lớp con kế thừa từ một lớp cha, các thành phần public và protected của lớp cha sẽ được kế thừa và có thể được truy cập từ bên trong lớp con. Tuy nhiên, các thành phần private và default của lớp cha chỉ có thể được truy cập từ bên trong lớp cha và không thể được truy cập từ bên trong lớp con.

public class Animal {

public String name;

protected int age;

private double weight;

public Animal(String name, int age, double weight) {

this.name = name;

this.age = age;

this.weight = weight;

}

public void eat() {

System.out.println(name + ” is eating”);

}

protected void sleep() {

System.out.println(name + ” is sleeping”);

}

private void move() {

System.out.println(name + ” is moving”);

}

}

public class Cat extends Animal {

public Cat(String name, int age, double weight) {

super(name, age, weight);

}

public void meow() {

System.out.println(name + ” is meowing”);

}

public void printInfo() {

System.out.println(“Name: ” + name);

System.out.println(“Age: ” + age);

// System.out.println(“Weight: ” + weight); // không thể truy cập thuộc tính private của lớp cha

eat();

sleep();

// move(); // không thể truy cập phương thức private của lớp cha

}

}

public class Main {

public static void main(String[] args) {

Cat cat = new Cat(“Whiskers”, 3, 5.5);

cat.name = “Mr. Whiskers”; // có thể truy cập thuộc tính public của lớp cha

cat.age = 4; // có thể truy cập thuộc tính protected của lớp cha

// cat.weight = 6.0; // không thể truy cập thuộc tính private của lớp cha từ bên ngoài lớp cha hoặc lớp con

cat.eat(); // có thể truy cập phương thức public của lớp cha

cat.sleep(); // có thể truy cập phương thức protected của lớp cha

// cat.move(); // không thể truy cập phương thức private của lớp cha từ bên ngoài lớp cha hoặc lớp con

cat.meow();

cat.printInfo();

}

}

Lớp Animal có các thuộc tính và phương thức được khai báo với các phạm vi truy cập khác nhau. Lớp Cat kế thừa từ lớp Animal và có thêm một phương thức meow() để in ra tiếng meo của mèo và phương thức printInfo() để in ra thông tin của đối tượng Cat.

Trong phương thức main(), chúng ta tạo ra một đối tượng Cat và truy cập các thành phần của lớp cha từ bên trong lớp con. Chúng ta có thể truy cập các thành phần public và protected của lớp cha từ bên trong lớp con, nhưng không thể truy cập các thành phần private của lớp cha từ bên ngoài lớp cha hoặc lớp con.

Chúng ta có thể thấy rằng, trong phương thức printInfo() của lớp Cat, chúng ta không thể truy cập thuộc tính private của lớp cha và phương thức private của lớp cha, mặc dù chúng được định nghĩa trong lớp cha.

Ưu điểm và nhược điểm của kế thừa trong Java

Kế thừa là một trong những tính năng quan trọng trong Java và nó có một số ưu điểm và nhược điểm sau:

Ưu điểm của kế thừa trong Java

  • Tái sử dụng code: Kế thừa cho phép sử dụng lại mã nguồn từ các lớp hiện có để tạo ra các lớp mới, giúp giảm thiểu việc lặp lại viết mã và tăng tính tái sử dụng của mã.
  • Dễ dàng bảo trì: Kế thừa giúp tách biệt các tính năng khác nhau của một chương trình thành các lớp khác nhau, giúp cho việc bảo trì và phát triển chương trình dễ dàng hơn.
  • Mở rộng tính năng: Kế thừa cho phép mở rộng tính năng của một lớp hiện có bằng cách thêm các tính năng mới vào lớp con.
  • Tăng tính linh hoạt: Kế thừa giúp tăng tính linh hoạt của chương trình, cho phép thay đổi hoặc bổ sung các tính năng của chương trình một cách dễ dàng hơn.

Nhược điểm của kế thừa trong Java

  • Nếu không được thiết kế đúng cách, kế thừa có thể dẫn đến mối quan hệ phức tạp giữa các lớp và tăng độ phức tạp của mã.
  • Kế thừa có thể dẫn đến việc đồng bộ hóa các lớp con với các lớp cha, khiến cho việc thay đổi một lớp có thể dẫn đến các thay đổi phức tạp trong các lớp con.
  • Kế thừa cũng có thể dẫn đến việc tạo ra các lớp con không cần thiết, khiến cho chương trình trở nên khó hiểu và khó bảo trì.
  • Kế thừa cũng có thể giới hạn tính đa hình của chương trình, khiến cho chương trình trở nên khó mở rộng và khó bảo trì.

Kết luận

Như vậy, qua bài viết này, chúng ta đã hiểu rõ hơn về khái niệm và một số vấn đề quan trọng về kế thừa trong Java. Hy vọng bài viết đã giúp bạn nắm vững hơn kỹ thuật lập trình hướng đối tượng thông qua ví dụ cụ thể về kế thừa.

Nếu bạn đang muốn tìm địa chỉ cung cấp khóa học lập trình Java uy tín, hãy tham khảo Rikkei Academy! Với lộ trình tinh gọn, bám sát thực tế, giảng viên hỗ trợ 24/7 giúp bạn nắm bắt sự nghiệp lập trình trong 6 tháng! Để tìm hiểu thêm thông tin chi tiết, đăng ký nhận tư vấn miễn phí ngay tại đây!