Kết quả 1 đến 2 của 2
  1. #1
    Ngày tham gia
    Feb 2015
    Bài viết
    0

    Tính kế thừa và tính trừu tượng trong Java



    [img]data/attachments/8/8567-8fe9b2ff777a0668c87b55bacbe4eef7.jpg[/img]

    kế thừa là gì? (đơn giản là "thừa kế" ^^)
    các lớp trong mã java tồn tại trong một hệ thống thứ bậc. các lớp ở bậc trên một lớp đã cho trong một hệ thống thứ bậc là các lớp bậc trên (superclasses) của lớp đó. lớp cụ thể đó là một lớp con (subclass) của tất cả các lớp bậc cao hơn. một lớp con thừa kế từ các lớp bậc trên của nó. lớp object ở trên đỉnh của mọi hệ thống thứ bậc các lớp. nói cách khác, mọi lớp là một lớp con của (và thừa kế từ) object.
    ví dụ, giả sử chúng ta có một lớp adult trông như sau:


    Mã nguồn PHP:
    [color=#000000]
    [/color][color=#007700]public class [/color][color=#0000bb]adult [/color][color=#007700]{protected [/color][color=#0000bb]int age [/color][color=#007700]= [/color][color=#0000bb]0[/color][color=#007700];protected [/color][color=#0000bb]string firstname [/color][color=#007700]= [/color][color=#dd0000]"firstname"[/color][color=#007700];protected [/color][color=#0000bb]string lastname [/color][color=#007700]= [/color][color=#dd0000]"lastname"[/color][color=#007700];protected [/color][color=#0000bb]string gender [/color][color=#007700]= [/color][color=#dd0000]"male"[/color][color=#007700];protected [/color][color=#0000bb]int progress [/color][color=#007700]= [/color][color=#0000bb]0[/color][color=#007700]; public [/color][color=#0000bb]adult[/color][color=#007700]() { }public [/color][color=#0000bb]void move[/color][color=#007700]() {[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"moved."[/color][color=#007700]);}public [/color][color=#0000bb]void talk[/color][color=#007700]() {[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"spoke."[/color][color=#007700]);}}[/color] 
    lớp adult của chúng ta kế thừa ngầm từ lớp object. điều này được thừa nhận cho mọi lớp, vì vậy bạn không phải gõ extends object trong định nghĩa lớp. nhưng nói rằng lớp của chúng ta thừa kế từ (các) lớp bậc trên của nó có nghĩa là gì? nó đơn giản có nghĩa là lớp adult có quyền truy cập vào các biến và các phương thức đã được trưng ra (exposed) trong các lớp bậc trên của nó. trong trường hợp này, nó muốn nói rằng lớp adult có thể thấy và sử dụng những phần sau đây từ bất kỳ các lớp bậc trên nào của nó (chúng ta chỉ có một vào lúc này):
    * các biến và phương thức công khai (public).
    * các biến và phương thức công khai có bảo vệ (protected).
    * các biến và phương thức có bảo vệ theo gói (package protected) (có nghĩa là, chúng không có từ đặc tả (specifier) quyền truy cập), nếu lớp bậc trên ở trong cùng một gói như lớp adult
    các hàm tạo là đặc biệt. chúng không phải là các thành viên hướng đối tượng (oo) đã đủ lông cánh, do đó chúng không được thừa kế.
    nếu một lớp con ghi đè một phương thức hay một biến từ lớp bậc trên — nói cách khác là khi lớp con triển khai thực hiện một thành viên có cùng tên — thì nó che dấu thành viên của lớp bậc trên. chính xác hơn, việc ghi đè một biến sẽ che giấu nó và việc ghi đè một phương thức chỉ đơn giản ghi đè nó, nhưng có hiệu quả tương tự nhau: thành viên bị ghi đè về cơ bản được ẩn đi. bạn vẫn có thể truy cập đến được các thành viên của lớp bậc trên bằng cách sử dụng từ khóa super:


    Mã nguồn PHP:
    super
    Mã nguồn PHP:
    [color=#0000bb]hiddenmembername[/color] 
    trong trường hợp lớp adult, tất cả những gì mà nó thừa kế vào lúc này là các phương thức về object (tostring(), chẳng hạn). do đó, các đoạn mã sau đây là hoàn toàn có thể chấp nhận được:


    Mã nguồn PHP:
    [color=#000000]
    adult anadult [/color][color=#007700]= new [/color][color=#0000bb]adult[/color][color=#007700]();[/color][color=#0000bb]anadult[/color][color=#007700].[/color][color=#0000bb]tostring[/color][color=#007700]();[/color] 
    phương thức tostring() không tồn tại rõ ràng trên lớp adult, nhưng lớp adult thừa kế nó.
    bạn hãy nên ghi nhớ rằng ở đây có các vụ “tìm ra rồi” (gotchas- nói về việc phát hiện ra nguyên nhân của một hành vi bất ngờ, không như mong đợi trong chương trình, tuy nhiên không phải là lỗi, vì tất cả đều đúng như tài liệu hướng dẫn). trước hết, rất dễ dàng đặt tên các biến và các phương thức trong một lớp con với tên giống như các biến và các phương thức trong các lớp bậc trên của lớp đó, rồi sau đó bị lẫn lộn khi bạn không thể gọi ra một phương thức được thừa kế. hãy nhớ rằng, khi bạn đưa ra một phương thức có cùng tên trong một lớp con giống như một lớp đã tồn tại trong một lớp bậc trên, bạn đã che giấu nó. thứ hai, các hàm tạo không được thừa kế, nhưng chúng được gọi ra. có một lời gọi ngầm đến hàm tạo của lớp bậc trên trong bất kỳ hàm tạo nào của lớp con được bạn viết và đó là điều đầu tiên mà hàm tạo của lớp con thực hiện. bạn phải sống chung với điều này; bạn không thể làm gì để thay đổi nó. ví dụ, hàm tạo adult của chúng ta thực sự trông như dưới đây khi thực chạy, mặc dù chúng ta không gõ bất cứ cái gì trong phần thân:


    Mã nguồn PHP:
    [color=#000000]
    [/color][color=#007700]public [/color][color=#0000bb]adult[/color][color=#007700]() {[/color][color=#0000bb]super[/color][color=#007700]();}[/color] 
    dòng đó trong phần thân của hàm tạo sẽ gọi hàm tạo không có đối số của lớp bậc trên. trong trường hợp này, đó là hàm tạo của object.

    định nghĩa một hệ thống thứ bậc các lớp
    giả chúng ta có một lớp có tên là baby. nó trong giống như thế này:


    Mã nguồn PHP:
    [color=#000000]
    [/color][color=#007700]public class [/color][color=#0000bb]baby [/color][color=#007700]{protected [/color][color=#0000bb]int age [/color][color=#007700]= [/color][color=#0000bb]0[/color][color=#007700];protected [/color][color=#0000bb]string firstname [/color][color=#007700]= [/color][color=#dd0000]"firstname"[/color][color=#007700];protected [/color][color=#0000bb]string lastname [/color][color=#007700]= [/color][color=#dd0000]"lastname"[/color][color=#007700];protected [/color][color=#0000bb]string gender [/color][color=#007700]= [/color][color=#dd0000]"male"[/color][color=#007700];protected [/color][color=#0000bb]int progress [/color][color=#007700]= [/color][color=#0000bb]0[/color][color=#007700]; public [/color][color=#0000bb]baby[/color][color=#007700]() {}public [/color][color=#0000bb]void move[/color][color=#007700]() {[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"moved."[/color][color=#007700]);}public [/color][color=#0000bb]void talk[/color][color=#007700]() {[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"spoke."[/color][color=#007700]);}}[/color] 
    các lớp adult and baby của chúng ta trông rất giống nhau. trong thực tế, chúng hầu như đồng nhất. việc sao đúp mã như thế làm cho việc bảo trì mã thêm khó khăn hơn mức cần thiết. chúng ta có thể tạo ra một lớp bậc trên, di chuyển tất cả các phần tử chung lên lớp đó và loại bỏ phần mã sao đúp. lớp bậc trên của chúng ta có thể được đặt tên là person và nó có thể trông giống như sau:


    Mã nguồn PHP:
    [color=#000000]
    [/color][color=#007700]public class [/color][color=#0000bb]person [/color][color=#007700]{protected [/color][color=#0000bb]int age [/color][color=#007700]= [/color][color=#0000bb]0[/color][color=#007700];protected [/color][color=#0000bb]string firstname [/color][color=#007700]= [/color][color=#dd0000]"firstname"[/color][color=#007700];protected [/color][color=#0000bb]string lastname [/color][color=#007700]= [/color][color=#dd0000]"lastname"[/color][color=#007700];protected [/color][color=#0000bb]string gender [/color][color=#007700]= [/color][color=#dd0000]"male"[/color][color=#007700];protected [/color][color=#0000bb]int progress [/color][color=#007700]= [/color][color=#0000bb]0[/color][color=#007700];public [/color][color=#0000bb]person[/color][color=#007700]() {}public [/color][color=#0000bb]void move[/color][color=#007700]() {[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"moved."[/color][color=#007700]);}public [/color][color=#0000bb]void talk[/color][color=#007700]() {[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"spoke."[/color][color=#007700]);}}[/color] 
    bây giờ chúng ta có thể để cho adult và baby làm lớp con của person, và làm cho hai lớp ấy thành khá đơn giản vào lúc này:


    Mã nguồn PHP:
    [color=#000000]
    [/color][color=#007700]public class [/color][color=#0000bb]adult [/color][color=#007700]{public [/color][color=#0000bb]adult[/color][color=#007700]() {}}public class [/color][color=#0000bb]baby [/color][color=#007700]{public [/color][color=#0000bb]baby[/color][color=#007700]() {}}[/color] 
    một khi chúng ta có hệ thống thứ bậc, chúng ta có thể tham chiếu một cá thể của mỗi lớp con như là một cá thể của bất kỳ các lớp bậc trên nào của nó trong hệ thống thứ bậc. ví dụ:


    Mã nguồn PHP:
    [color=#000000]
    adult anadult [/color][color=#007700]= new [/color][color=#0000bb]adult[/color][color=#007700]();[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"anadult is an object: " [/color][color=#007700]+ ([/color][color=#0000bb]adult [/color][color=#007700]instanceof [/color][color=#0000bb]object[/color][color=#007700]));[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"anadult is a person: " [/color][color=#007700]+ ([/color][color=#0000bb]adult [/color][color=#007700]instanceof [/color][color=#0000bb]person[/color][color=#007700]));[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"anadult is anadult: " [/color][color=#007700]+ ([/color][color=#0000bb]adult [/color][color=#007700]instanceof [/color][color=#0000bb]adult[/color][color=#007700]));[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"anadult is a baby: " [/color][color=#007700]+ ([/color][color=#0000bb]adult [/color][color=#007700]instanceof [/color][color=#0000bb]baby[/color][color=#007700]));[/color][color=#0000bb]adult anadult [/color][color=#007700]= new [/color][color=#0000bb]adult[/color][color=#007700]();[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"anadult is an object: " [/color][color=#007700]+ ([/color][color=#0000bb]adult [/color][color=#007700]instanceof [/color][color=#0000bb]object[/color][color=#007700]));[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"anadult is a person: " [/color][color=#007700]+ ([/color][color=#0000bb]adult [/color][color=#007700]instanceof [/color][color=#0000bb]person[/color][color=#007700]));[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"anadult is anadult: " [/color][color=#007700]+ ([/color][color=#0000bb]adult [/color][color=#007700]instanceof [/color][color=#0000bb]adult[/color][color=#007700]));[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"anadult is a baby: " [/color][color=#007700]+ ([/color][color=#0000bb]adult [/color][color=#007700]instanceof [/color][color=#0000bb]baby[/color][color=#007700]));[/color] 
    mã này sẽ cho chúng ta ba kết quả đúng và một kết quả sai. bạn cũng có thể ép kiểu (cast) một đối tượng thành bất kỳ kiểu bậc cao hơn nào trong hệ thống thứ bậc của nó, như dưới đây:


    Mã nguồn PHP:
    [color=#000000]
    adult anadult [/color][color=#007700]= new [/color][color=#0000bb]adult[/color][color=#007700]();[/color][color=#0000bb]person aperson [/color][color=#007700]= ([/color][color=#0000bb]person[/color][color=#007700]) [/color][color=#0000bb]anadult[/color][color=#007700];[/color][color=#0000bb]aperson[/color][color=#007700].[/color][color=#0000bb]move[/color][color=#007700]();[/color] 
    mã này sẽ biên dịch mà không có vấn đề gì. chúng ta có thể ép kiểu một adult thành kiểu person, sau đó gọi một phương thức person trên đó.
    do chúng ta có hệ thống thứ bậc này, nên mã trên các lớp con của chúng ta đơn giản hơn. nhưng bạn có thấy một vấn đề ở đây không? bây giờ tất cả các adult và và tất cả các baby (thứ lỗi vì việc dùng từ số nhiều không đúng) sẽ nói năng và đi lại theo cùng một cách. chỉ có duy nhất một triển khai thực hiện cho mỗi hành vi. đó không phải là những gì mà chúng ta muốn, bởi vì những người trưởng thành không nói năng hoặc đi lại giống như trẻ con. chúng ta có thể ghi đè move() và talk() trong các lớp con, nhưng sau đó về cơ bản chúng ta không sử dụng được hành vi “tiêu chuẩn” đã định nghĩa trong lớp bậc trên của chúng ta. cái mà chúng ta thực sự muốn là một cách để bắt buộc các lớp con của chúng ta đi lại và nói năng theo cách cụ thể riêng của chúng. đó là những gì mà các lớp trừu tượng sẽ làm.định nghĩa một hệ thống thứ bậc các lớp
    giả chúng ta có một lớp có tên là baby. nó trong giống như thế này:


    Mã nguồn PHP:
    [color=#000000]
    [/color][color=#007700]public class [/color][color=#0000bb]baby [/color][color=#007700]{protected [/color][color=#0000bb]int age [/color][color=#007700]= [/color][color=#0000bb]0[/color][color=#007700];protected [/color][color=#0000bb]string firstname [/color][color=#007700]= [/color][color=#dd0000]"firstname"[/color][color=#007700];protected [/color][color=#0000bb]string lastname [/color][color=#007700]= [/color][color=#dd0000]"lastname"[/color][color=#007700];protected [/color][color=#0000bb]string gender [/color][color=#007700]= [/color][color=#dd0000]"male"[/color][color=#007700];protected [/color][color=#0000bb]int progress [/color][color=#007700]= [/color][color=#0000bb]0[/color][color=#007700]; public [/color][color=#0000bb]baby[/color][color=#007700]() {}public [/color][color=#0000bb]void move[/color][color=#007700]() {[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"moved."[/color][color=#007700]);}public [/color][color=#0000bb]void talk[/color][color=#007700]() {[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"spoke."[/color][color=#007700]);}}[/color] 
    các lớp adult and baby của chúng ta trông rất giống nhau. trong thực tế, chúng hầu như đồng nhất. việc sao đúp mã như thế làm cho việc bảo trì mã thêm khó khăn hơn mức cần thiết. chúng ta có thể tạo ra một lớp bậc trên, di chuyển tất cả các phần tử chung lên lớp đó và loại bỏ phần mã sao đúp. lớp bậc trên của chúng ta có thể được đặt tên là person và nó có thể trông giống như sau:


    Mã nguồn PHP:
    [color=#000000]
    [/color][color=#007700]public class [/color][color=#0000bb]person [/color][color=#007700]{protected [/color][color=#0000bb]int age [/color][color=#007700]= [/color][color=#0000bb]0[/color][color=#007700];protected [/color][color=#0000bb]string firstname [/color][color=#007700]= [/color][color=#dd0000]"firstname"[/color][color=#007700];protected [/color][color=#0000bb]string lastname [/color][color=#007700]= [/color][color=#dd0000]"lastname"[/color][color=#007700];protected [/color][color=#0000bb]string gender [/color][color=#007700]= [/color][color=#dd0000]"male"[/color][color=#007700];protected [/color][color=#0000bb]int progress [/color][color=#007700]= [/color][color=#0000bb]0[/color][color=#007700];public [/color][color=#0000bb]person[/color][color=#007700]() {}public [/color][color=#0000bb]void move[/color][color=#007700]() {[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"moved."[/color][color=#007700]);}public [/color][color=#0000bb]void talk[/color][color=#007700]() {[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"spoke."[/color][color=#007700]);}}[/color] 
    bây giờ chúng ta có thể để cho adult và baby làm lớp con của person, và làm cho hai lớp ấy thành khá đơn giản vào lúc này:


    Mã nguồn PHP:
    [color=#000000]
    [/color][color=#007700]public class [/color][color=#0000bb]adult [/color][color=#007700]{public [/color][color=#0000bb]adult[/color][color=#007700]() {}}public class [/color][color=#0000bb]baby [/color][color=#007700]{public [/color][color=#0000bb]baby[/color][color=#007700]() {}}[/color] 
    một khi chúng ta có hệ thống thứ bậc, chúng ta có thể tham chiếu một cá thể của mỗi lớp con như là một cá thể của bất kỳ các lớp bậc trên nào của nó trong hệ thống thứ bậc. ví dụ:


    Mã nguồn PHP:
    [color=#000000]
    adult anadult [/color][color=#007700]= new [/color][color=#0000bb]adult[/color][color=#007700]();[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"anadult is an object: " [/color][color=#007700]+ ([/color][color=#0000bb]adult [/color][color=#007700]instanceof [/color][color=#0000bb]object[/color][color=#007700]));[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"anadult is a person: " [/color][color=#007700]+ ([/color][color=#0000bb]adult [/color][color=#007700]instanceof [/color][color=#0000bb]person[/color][color=#007700]));[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"anadult is anadult: " [/color][color=#007700]+ ([/color][color=#0000bb]adult [/color][color=#007700]instanceof [/color][color=#0000bb]adult[/color][color=#007700]));[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"anadult is a baby: " [/color][color=#007700]+ ([/color][color=#0000bb]adult [/color][color=#007700]instanceof [/color][color=#0000bb]baby[/color][color=#007700]));[/color] 
    mã này sẽ cho chúng ta ba kết quả đúng và một kết quả sai. bạn cũng có thể ép kiểu (cast) một đối tượng thành bất kỳ kiểu bậc cao hơn nào trong hệ thống thứ bậc của nó, như dưới đây:


    Mã nguồn PHP:
    [color=#000000]
    adult anadult [/color][color=#007700]= new [/color][color=#0000bb]adult[/color][color=#007700]();[/color][color=#0000bb]person aperson [/color][color=#007700]= ([/color][color=#0000bb]person[/color][color=#007700]) [/color][color=#0000bb]anadult[/color][color=#007700];[/color][color=#0000bb]aperson[/color][color=#007700].[/color][color=#0000bb]move[/color][color=#007700]();[/color] 
    mã này sẽ biên dịch mà không có vấn đề gì. chúng ta có thể ép kiểu một adult thành kiểu person, sau đó gọi một phương thức person trên đó.
    do chúng ta có hệ thống thứ bậc này, nên mã trên các lớp con của chúng ta đơn giản hơn. nhưng bạn có thấy một vấn đề ở đây không? bây giờ tất cả các adult và và tất cả các baby (thứ lỗi vì việc dùng từ số nhiều không đúng) sẽ nói năng và đi lại theo cùng một cách. chỉ có duy nhất một triển khai thực hiện cho mỗi hành vi. đó không phải là những gì mà chúng ta muốn, bởi vì những người trưởng thành không nói năng hoặc đi lại giống như trẻ con. chúng ta có thể ghi đè move() và talk() trong các lớp con, nhưng sau đó về cơ bản chúng ta không sử dụng được hành vi “tiêu chuẩn” đã định nghĩa trong lớp bậc trên của chúng ta. cái mà chúng ta thực sự muốn là một cách để bắt buộc các lớp con của chúng ta đi lại và nói năng theo cách cụ thể riêng của chúng. đó là những gì mà các lớp trừu tượng sẽ làm.

    trừu tượng hóa
    trong bối cảnh hướng đối tượng, trừu tượng hóa đề cập đến hoạt động tổng quát hóa dữ liệu và hành vi thành một kiểu bậc cao hơn so với lớp hiện tại trong hệ thống thứ bậc. khi bạn di chuyển các biến hoặc các phương thức từ một lớp con vào một lớp bậc trên, bạn đang trừu tượng hóa các thành viên này.
    đó là các thuật ngữ chung và chúng cũng được áp dụng trong ngôn ngữ java. nhưng ngôn ngữ java cũng bổ sung thêm các khái niệm về các lớp trừu tượng và các phương thức trừu tượng. lớp trừu tượng là một lớp không cá thể hóa được. ví dụ, bạn có thể tạo ra một lớp có tên là animal. việc tạo ra một cá thể từ lớp như vậy sẽ không có ý nghĩa: trong thực tế, bạn chỉ muốn tạo ra các cá thể của một lớp cụ thể như dog. nhưng tất cả các animal có một số điểm chung, chẳng hạn như khả năng kêu. việc nói rằng một animal kêu không cho bạn biết gì nhiều. tiếng kêu thế nào phụ thuộc vào loại động vật. làm thế nào để mô hình hóa điều đó? bạn định nghĩa các điểm chung trong các lớp trừu tượng và bạn bắt buộc các lớp con triển khai thực hiện hành vi cụ thể đặc thù cho loài của chúng.
    bạn có thể có cả lớp trừu tượng và lớp cụ thể trong hệ thống thứ bậc của bạn.

    sử dụng lớp trừu tượng

    lớp person của chúng ta chứa một số phương thức hành vi mà chúng ta còn chưa biết là chúng ta cần hay không. hãy gỡ bỏ nó và bắt buộc các lớp con triển khai thực hiện hành vi đó một cách đa dạng. chúng ta có thể làm điều đó bằng cách định nghĩa các phương thức của person là trừu tượng. sau đó, các lớp con của chúng ta sẽ phải triển khai thực hiện các phương thức đó.


    Mã nguồn PHP:
    [color=#000000]
    [/color][color=#007700]public abstract class [/color][color=#0000bb]person [/color][color=#007700]{...abstract [/color][color=#0000bb]void move[/color][color=#007700]();abstract [/color][color=#0000bb]void talk[/color][color=#007700]();} public class [/color][color=#0000bb]adult [/color][color=#007700]extends [/color][color=#0000bb]person [/color][color=#007700]{public [/color][color=#0000bb]adult[/color][color=#007700]() {}public [/color][color=#0000bb]void move[/color][color=#007700]() {[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"walked."[/color][color=#007700]);}public [/color][color=#0000bb]void talk[/color][color=#007700]() {[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"spoke."[/color][color=#007700]);}} public class [/color][color=#0000bb]baby [/color][color=#007700]extends [/color][color=#0000bb]person [/color][color=#007700]{public [/color][color=#0000bb]baby[/color][color=#007700]() {}public [/color][color=#0000bb]void move[/color][color=#007700]() {[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"crawled."[/color][color=#007700]);}public [/color][color=#0000bb]void talk[/color][color=#007700]() {[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"gurgled."[/color][color=#007700]);}}[/color] 
    chúng ta đã thực hiện những gì trong bản listing này?
    • chúng ta đã thay đổi person làm cho các phương thức thành trừu tượng, bắt buộc các lớp con triển khai thực hiện chúng.
    • chúng ta làm cho adult thành lớp con của person và triển khai thực hiện các phương thức.
    • chúng ta làm cho baby thành lớp con của person và triển khai thực hiện các phương thức.
    khi bạn khai báo một phương thức là trừu tượng, bạn cần các lớp con để thực hiện phương thức, hoặc chính lớp con lại tiếp tục là trừu tượng và chuyển giao trách nhiệm triển khai thực hiện tới các lớp con bậc dưới nữa. bạn có thể thực hiện một số phương thức trên lớp trừu tượng và buộc các lớp con thực hiện những phương thức khác. điều này tùy thuộc vào bạn. đơn giản chỉ cần khai báo những cái bạn không muốn triển khai thực hiện là trừu tượng và không cung cấp phần thân của phương thức. nếu một lớp con không thực hiện một phương thức trừu tượng từ một lớp bậc trên, thì trình biên dịch sẽ báo lỗi.
    vì cả hai adult và baby đều là lớp con của person, chúng ta có thể quy một cá thể của mỗi lớp là thuộc kiểu person.

    cấu trúc lại thành hành vi trừu tượng
    bây giờ chúng ta đã có lớp person, adult và baby trong hệ thống thứ bậc của chúng ta. giả chúng ta muốn làm cho hai lớp con thực tế hơn bằng cách thay đổi các phương thức move() của chúng như sau:


    Mã nguồn PHP:
    [color=#000000]
    [/color][color=#007700]public class [/color][color=#0000bb]adult [/color][color=#007700]extends [/color][color=#0000bb]person [/color][color=#007700]{...public [/color][color=#0000bb]void move[/color][color=#007700]() {[/color][color=#0000bb]this[/color][color=#007700].[/color][color=#0000bb]progress[/color][color=#007700]++;}...} public class [/color][color=#0000bb]baby [/color][color=#007700]extends [/color][color=#0000bb]person [/color][color=#007700]{...public [/color][color=#0000bb]void move[/color][color=#007700]() {[/color][color=#0000bb]this[/color][color=#007700].[/color][color=#0000bb]progress[/color][color=#007700]++;}...}[/color] 
    bây giờ mỗi lớp cập nhật biến cá thể của nó để phản ánh một tiến triển nào đó đang được thực hiện mỗi khi chúng ta gọi move(). tuy nhiên, cần lưu ý rằng hành vi lại vẫn giống nhau. cấu trúc lại mã để loại bỏ sao đúp mã là có ý nghĩa. việc cấu trúc lại thích hợp nhất là di chuyển move() tới person.
    đúng, chúng ta đang thêm việc triển khai thực hiện phương thức quay trở lại lớp bậc trên mà chúng ta vừa lấy nó ra. đây là một ví dụ rất đơn giản, do đó việc chuyển qua chuyển lại này có vẻ quá lãng phí. nhưng những gì mà chúng ta vừa trải qua là phổ biến khi bạn viết mã java. bạn thường xuyên thấy các lớp và các phương thức thay đổi khi hệ thống lớn lên và đôi khi bạn đi đến chỗ có sao đúp mã mà bạn có thể cấu trúc lại, đưa vào các lớp bậc trên. thậm chí bạn có thể làm điều đó, sau đó quyết định rằng đây là một sai lầm và đưa hành vi quay trở lại xuống các lớp con. đơn giản là có thể bạn không biết vị trí thích đáng của tất cả các hành vi tại thời điểm bắt đầu quá trình phát triển. bạn chỉ biết được vị trí thích đáng dành cho hành vi khi bạn tiến lên.
    hãy cấu trúc lại các lớp của chúng ta để đặt move() quay lại lớp bậc trên:


    Mã nguồn PHP:
    [color=#000000]
    [/color][color=#007700]public abstract class [/color][color=#0000bb]person [/color][color=#007700]{...public [/color][color=#0000bb]void move[/color][color=#007700]() {[/color][color=#0000bb]this[/color][color=#007700].[/color][color=#0000bb]progress[/color][color=#007700]++;}public abstract [/color][color=#0000bb]void talk[/color][color=#007700]();} public class [/color][color=#0000bb]adult [/color][color=#007700]extends [/color][color=#0000bb]person [/color][color=#007700]{public [/color][color=#0000bb]adult[/color][color=#007700]() {}public [/color][color=#0000bb]void talk[/color][color=#007700]() {[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"spoke."[/color][color=#007700]);}} public class [/color][color=#0000bb]baby [/color][color=#007700]extends [/color][color=#0000bb]person [/color][color=#007700]{public [/color][color=#0000bb]baby[/color][color=#007700]() {}public [/color][color=#0000bb]void talk[/color][color=#007700]() {[/color][color=#0000bb]system[/color][color=#007700].[/color][color=#0000bb]out[/color][color=#007700].[/color][color=#0000bb]println[/color][color=#007700]([/color][color=#dd0000]"gurgled."[/color][color=#007700]);}}[/color] 
    bây giờ các lớp con của chúng ta triển khai thực hiện các phiên bản khác nhau của talk(), nhưng chia sẻ cùng một hành vi

    khi nào trừu tượng hóa… và khi nào thì không
    việc quyết định khi nào trừu tượng hóa (hay tạo một hệ thống thứ bậc) là một chủ đề tranh luận nóng trong giới hướng đối tượng, đặc biệt là giữa các lập trình viên ngôn ngữ java. chắc chắn có rất ít các câu trả lời đúng hoặc sai về cách làm thế nào để cấu trúc hệ thống thứ bậc các lớp. đây là một lĩnh vực ở đó các nhà thực hành có tay nghề và tận tâm có thể (và thường xuyên là) không đồng ý với nhau. dù sao đi nữa, có một số quy tắc ngón tay cái thích hợp phải theo đối với các hệ thống thứ bậc.
    thứ nhất, không trừu tượng hóa ngay từ đầu. hãy đợi cho đến khi mã thông báo cho bạn rằng bạn nên trừu tượng hóa. cấu trúc lại trên đường bạn đi đến trừu tượng hóa luôn luôn là cách tốt hơn là giả định bạn cần nó ngay ở lúc bắt đầu. đừng giả định rằng bạn cần có một hệ thống thứ bậc. nhiều lập trình viên java lạm dụng các hệ thống thứ bậc.
    thứ hai, chống lại việc sử dụng các lớp trừu tượng khi bạn có thể. chúng không phải là xấu, chúng chỉ có các hạn chế. chúng ta thường sử dụng một lớp trừu tượng để bắt buộc các lớp con của chúng ta triển khai hành vi nhất định nào đó. một giao diện (mà chúng ta sẽ thảo luận trong phần các giao diện ) có phải là một ý tưởng tốt hơn không? hoàn toàn có thể. mã của bạn sẽ là dễ hiểu hơn nếu nó không tạo nên một hệ thống thứ bậc phức tạp với một hỗn hợp các phương thức triển khai thực hiện và ghi đè. bạn có thể có một phương thức được định nghĩa xuyên qua ba hoặc bốn lớp, thành một dãy. thời điểm mà bạn sử dụng nó trong một lớp con của lớp con của lớp con của lớp con (sub-sub-sub-subclass), bạn có thể phải tìm kiếm lâu để phát hiện phương thức này sẽ làm gì. điều đó có thể làm nản lòng việc gỡ rối.
    thứ ba, hãy sử dụng một hệ thống thứ bậc và/hoặc các lớp trừu tượng khi làm như thế là đẹp. có rất nhiều mẫu mã lệnh sử dụng các khái niệm phương thức trừu tượng và lớp trừu tượng của ngôn ngữ java, ví dụ như mẫu phương thức khuôn mẫu gang of four
    thứ tư, hiểu được giá mà bạn phải trả khi bạn sử dụng một hệ thống thứ bậc một cánh vội vã. nó thực sự có thể dẫn bạn nhanh chóng rơi vào con đường sai lầm, bởi vì có các lớp ở đó rồi, được đặt tên như vậy, với các phương thức mà chúng đã có, làm cho rất dễ dàng để cho rằng tất cả những thứ đó nên là như thế. có lẽ rằng hệ thống thứ bậc có ý nghĩa khi bạn tạo ra nó, nhưng nó có thể không có ý nghĩa gì hơn nữa. sức ỳ có thể chống lại các đổi thay.
    nói tóm lại, hãy khôn khéo khi sử dụng các hệ thống thứ bậc. kinh nghiệm sẽ giúp bạn khôn ngoan hơn, nhưng nó sẽ không làm cho bạn lúc nào cũng sáng suốt. hãy nhớ cấu trúc lại.

  2. #2
    Ngày tham gia
    Jan 2015
    Bài viết
    0
    hình như bác long lấy trên java ibm đúng không, thấy quen lắm à :d

Quyền viết bài

  • Bạn Không thể gửi Chủ đề mới
  • Bạn Không thể Gửi trả lời
  • Bạn Không thể Gửi file đính kèm
  • Bạn Không thể Sửa bài viết của mình
  •