CodeGym/Blog Java/Ngẫu nhiên/Ví dụ cụ thể về lớp trừu tượng trong Java

Ví dụ cụ thể về lớp trừu tượng trong Java

Xuất bản trong nhóm
CHÀO! Trong các bài học trước, chúng ta đã gặp các giao diện và tìm hiểu xem chúng dùng để làm gì. Chủ đề hôm nay sẽ lặp lại chủ đề trước đó. Hãy nói về các lớp trừu tượng trong Java. Ví dụ cụ thể về lớp trừu tượng trong Java - 1

Tại sao các lớp được gọi là 'trừu tượng'

Bạn có thể nhớ 'trừu tượng' là gì - chúng ta đã xem qua nó. :) Nếu bạn quên, đừng sợ. Hãy nhớ rằng: đó là một nguyên tắc của OOP nói rằng khi thiết kế các lớp và tạo các đối tượng, chúng ta chỉ nên xác định các thuộc tính chính của thực thể và loại bỏ các thuộc tính phụ. Ví dụ: nếu chúng ta đang thiết kế một SchoolTeacherlớp, chúng ta hầu như không cần thuộc tính ' height '. Thật vậy, tài sản này là không thích hợp cho một giáo viên. Nhưng nếu chúng ta đang tạo một BasketballPlayerlớp, thì sự phát triển sẽ là một đặc điểm quan trọng. Vì vậy, lắng nghe. Một lớp trừu tượngcũng trừu tượng như chúng đến - một 'khoảng trống' chưa hoàn thành cho một nhóm các lớp học trong tương lai. Chỗ trống không thể được sử dụng nguyên trạng. Nó quá 'thô'. Nhưng nó mô tả trạng thái nhất định và hành vi chung sẽ được sở hữu bởi các lớp tương lai kế thừa lớp trừu tượng.

Ví dụ về các lớp Java trừu tượng

Hãy xem xét một ví dụ đơn giản với ô tô:
public abstract class Car {

   private String model;
   private String color;
   private int maxSpeed;

   public abstract void gas();

   public abstract void brake();

   public String getModel() {
       return model;
   }

   public void setModel(String model) {
       this.model = model;
   }

   public String getColor() {
       return color;
   }

   public void setColor(String color) {
       this.color = color;
   }

   public int getMaxSpeed() {
       return maxSpeed;
   }

   public void setMaxSpeed(int maxSpeed) {
       this.maxSpeed = maxSpeed;
   }
}
Đây là giao diện của lớp trừu tượng đơn giản nhất. Như bạn có thể thấy, nó không có gì đặc biệt :) Tại sao chúng ta cần nó? Trước hết, nó mô tả thực thể cần thiết của chúng ta, một chiếc ô tô, theo cách trừu tượng nhất có thể. Có một lý do tại sao chúng tôi đang sử dụng từ trừu tượng . Trong thế giới thực, không có 'chiếc xe trừu tượng'. Có xe tải, xe đua, sedan, coupe và SUV. Lớp trừu tượng của chúng tôi chỉ đơn giản là một 'bản thiết kế' mà chúng tôi sẽ sử dụng sau này để tạo các lớp ô tô.
public class Sedan extends Car {

   @Override
   public void gas() {
       System.out.println("The sedan is accelerating!");
   }

   @Override
   public void brake() {
       System.out.println("The sedan is slowing down!");
   }

}
Điều này rất giống với những gì chúng ta đã nói trong các bài học về thừa kế. Nhưng trong những bài học đó, chúng ta có một lớp Car và các phương thức của nó không trừu tượng. Nhưng giải pháp đó có một số nhược điểm được khắc phục trong các lớp trừu tượng. Trước hết, bạn không thể tạo một thể hiện của một lớp trừu tượng :
public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // Error! The Car class is abstract!
   }
}
Những người tạo ra Java đã thiết kế đặc biệt 'tính năng' này. Xin nhắc lại một lần nữa: lớp trừu tượng chỉ là bản thiết kế cho các lớp 'bình thường' trong tương lai . Bạn không cần bản sao của bản thiết kế, phải không? Và bạn không tạo các thể hiện của một lớp trừu tượng :) Nhưng nếu lớp Carkhông trừu tượng, chúng ta có thể dễ dàng tạo các thể hiện của nó:
public class Car {

   private String model;
   private String color;
   private int maxSpeed;

   public void gas() {
       // Some logic
   }

    public void brake() {
       // Some logic
   }
}


public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // Everything is fine. A car is created.
   }
}
Bây giờ chương trình của chúng tôi có một số loại ô tô khó hiểu — nó không phải xe tải, không phải xe đua, không phải sedan và hoàn toàn không rõ nó là gì. Đây là 'chiếc xe trừu tượng' không tồn tại trong tự nhiên. Chúng tôi có thể cung cấp ví dụ tương tự bằng cách sử dụng động vật. Hãy tưởng tượng nếu Animalcác lớp ( động vật trừu tượng ). Không rõ nó là loại động vật gì, thuộc họ gì và có đặc điểm gì. Sẽ là lạ khi thấy điều đó trong chương trình của bạn. Không có 'động vật trừu tượng' trong tự nhiên. Chỉ chó, mèo, cáo, chuột chũi, v.v. Các lớp trừu tượng giải phóng chúng ta khỏi các đối tượng trừu tượng. Chúng cung cấp cho chúng ta trạng thái và hành vi cơ bản. Ví dụ: tất cả ô tô phải có kiểu xe , màu sắctốc độ tối đa và bạn sẽ có thể áp dụnggaphanh . Đó là nó. Đây là một kế hoạch trừu tượng chung. Tiếp theo, bạn thiết kế các lớp bạn cần. Lưu ý: hai phương thức trong lớp trừu tượng cũng được chỉ định là trừu tượng và chúng không có bất kỳ triển khai nào. Lý do là như nhau: các lớp trừu tượng không tạo hành vi mặc định cho những chiếc xe trừu tượng. Họ chỉ chỉ ra những gì mọi chiếc xe sẽ có thể làm. Tuy nhiên, nếu bạn cần hành vi mặc định, bạn có thể triển khai các phương thức trong một lớp trừu tượng. Java không cấm điều này:
public abstract class Car {

   private String model;
   private String color;
   private int maxSpeed;

   public void gas() {
       System.out.println("Gas!");
   }

   public abstract void brake();

   // Getters and setters
}


public class Sedan extends Car {

   @Override
   public void brake() {
       System.out.println("The sedan is slowing down!");
   }

}

public class Main {

   public static void main(String[] args) {

       Sedan sedan = new Sedan();
       sedan.gas();
   }
}
Đầu ra của bảng điều khiển: “Gas!" Như bạn có thể thấy, chúng tôi đã triển khai phương thức đầu tiên trong lớp trừu tượng chứ không phải phương thức thứ hai. Kết quả là, Sedanhành vi của lớp chúng tôi được chia thành hai phần: nếu bạn gọi phương gas()thức, thì cuộc gọi 'tăng' lên đến Carlớp cha trừu tượng, nhưng chúng ta đã ghi đè lên brake()phương thức trong Sedanlớp. Điều này hóa ra rất thuận tiện và linh hoạt. Nhưng bây giờ lớp của chúng ta không trừu tượng như vậy nữa ? Rốt cuộc, một nửa số phương thức của nó đã được triển khai. Điều này thực sự là một tính năng rất quan trọng - một lớp là trừu tượng nếu ít nhất một trong các phương thức của nó là trừu tượng. Một trong hai phương pháp, hoặc ít nhất là một trong hàng nghìn phương pháp - không có gì khác biệt. Chúng ta thậm chí có thể triển khai tất cả các phương thức và không để lại phương thức trừu tượng nào. Sau đó, nó sẽ là một lớp trừu tượng không có phương thức trừu tượng. Về nguyên tắc, điều này là có thể, và trình biên dịch sẽ không tạo ra lỗi, nhưng tốt hơn hết là nên tránh nó: Từ trừu tượng mất đi ý nghĩa của nó, và các lập trình viên đồng nghiệp của bạn sẽ rất ngạc nhiên :/ Đồng thời, nếu một phương thức được đánh dấu với từ trừu tượng, mỗi lớp con phải thực hiện nó hoặc khai báo nó là trừu tượng. Nếu không, trình biên dịch sẽ phát sinh lỗi. Tất nhiên, mỗi lớp chỉ được kế thừa một lớp trừu tượng nên về mặt kế thừa không có sự khác biệt giữa lớp trừu tượng và lớp thường. Không quan trọng chúng ta kế thừa một lớp trừu tượng hay lớp thông thường, chỉ có thể có một lớp cha.

Tại sao Java không có nhiều lớp kế thừa

Chúng tôi đã nói rằng Java không có đa kế thừa, nhưng chúng tôi chưa thực sự khám phá lý do tại sao. Hãy thử làm điều đó ngay bây giờ. Thực tế là nếu Java có nhiều kế thừa, các lớp con sẽ không thể quyết định chúng nên chọn hành vi cụ thể nào. Giả sử chúng ta có hai lớp — ToasterNuclearBomb:
public class Toaster {


 public void on() {

       System.out.println("The toaster is on. Toast is being prepared!");
   }

   public void off() {

       System.out.println("The toaster is off!");
   }
}


public class NuclearBomb {

   public void on() {

       System.out.println("Boom!");
   }
}
Như bạn có thể thấy, cả hai đều có một on()phương pháp. Đối với máy nướng bánh mì, nó bắt đầu nướng. Đối với một quả bom hạt nhân, nó gây ra một vụ nổ. Rất tiếc: / Bây giờ hãy tưởng tượng rằng bạn đã quyết định (đừng hỏi tôi tại sao!) để tạo ra thứ gì đó ở giữa. Và do đó bạn có một MysteriousDevicelớp học! Tất nhiên, mã này không hoạt động và chúng tôi chỉ cung cấp mã này làm ví dụ 'nhưng có thể':
public class MysteriousDevice extends Toaster, NuclearBomb {

   public static void main(String[] args) {

       MysteriousDevice mysteriousDevice = new MysteriousDevice();
       mysteriousDevice.on(); // So what should happen here? Do we get toast or a nuclear apocalypse?
   }
}
Hãy xem những gì chúng ta có. Thiết bị bí ẩn đồng thời kế thừa Toaster và NuclearBomb. Cả hai đều có on()phương pháp. Kết quả là, nếu chúng ta gọi on()phương thức, sẽ không rõ phương thức nào sẽ được gọi trên MysteriousDeviceđối tượng. Không đời nào đối tượng có thể biết được. Và trên hết: Bom hạt nhân không có off()phương pháp, vì vậy nếu chúng tôi không đoán đúng, sẽ không thể vô hiệu hóa thiết bị. Ví dụ cụ thể về lớp trừu tượng trong Java - 2Chính vì sự 'nhầm lẫn' này, trong đó đối tượng không biết phải thể hiện hành vi nào, mà những người tạo ra Java đã từ bỏ đa kế thừa. Tuy nhiên, bạn sẽ nhớ lại rằng các lớp Java có thể triển khai nhiều giao diện. Nhân tiện, trong nghiên cứu của bạn, bạn đã gặp ít nhất một lớp trừu tượng!
public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar>
Đó là bạn cũ của bạn, cùng Calendarlớp. Nó trừu tượng và có nhiều con. Một trong số đó là GregorianCalendar. Bạn đã sử dụng nó trong các bài học về ngày tháng. :) Mọi thứ dường như đủ rõ ràng. Chỉ có một câu hỏi: sự khác biệt cơ bản giữa các lớp trừu tượng và giao diện là gì? Tại sao họ thêm cả hai vào Java thay vì chỉ giới hạn ngôn ngữ thành một? Rốt cuộc, điều đó sẽ hoàn toàn phù hợp. Chúng ta sẽ nói về điều này trong bài học tiếp theo ! Cho đến lúc đó :)
Bình luận
  • Phổ biến
  • Mới
Bạn phải đăng nhập để đăng nhận xet
Trang này chưa có bất kỳ bình luận nào