2012-08-15 31 views
68

thể trùng lặp:
Abstraction VS Information Hiding VS EncapsulationAbstraction vs Đóng gói trong Java

Tôi biết câu hỏi này có thể đã bị hỏi hàng ngàn lần trên diễn đàn này, thậm chí ròng cũng được làm đầy với rất nhiều định nghĩa về những khái niệm này nhưng tất cả đều giống nhau và tất cả đều sử dụng các từ kỹ thuật giống nhau. Ví dụ: các định nghĩa sau đây

Đóng gói là một quá trình ràng buộc hoặc gói dữ liệu và mã hoạt động trên dữ liệu vào một thực thể duy nhất. Điều này giữ cho dữ liệu an toàn từ giao diện bên ngoài và sử dụng sai. Một cách để suy nghĩ về đóng gói là một trình bao bọc bảo vệ ngăn mã và dữ liệu bị truy cập tùy ý bởi mã khác được xác định bên ngoài trình bao bọc.

Điều tôi hiểu từ định nghĩa ở trên là tạo biến, đánh dấu chúng riêng và tạo bộ getter-setter cho các biến đó và sử dụng đối tượng để truy cập getter và setter đó. Theo cách đó, dữ liệu được ẩn bên trong đối tượng và chỉ có thể truy cập thông qua đối tượng. Hy vọng tôi là đúng.


Abstraction là quá trình trừu tượng trong Java được sử dụng để ẩn chi tiết nhất định và chỉ hiển thị các tính năng cần thiết của đối tượng. Nói cách khác, nó đề cập đến giao diện bên ngoài của một đối tượng (giao diện).

Bây giờ đây là phần luôn làm tôi bối rối. Bất cứ khi nào tôi nghĩ về sự trừu tượng, điều đến với tâm trí của tôi là lớp Tóm tắt (có thể vì cả hai đều có từ khóa Tóm tắt). Định nghĩa trên cho biết trừu tượng có nghĩa là ẩn dữ liệu và chỉ hiển thị các chi tiết được yêu cầu nhưng đó là những gì chúng tôi đã làm trong đóng gói đúng không? thì sự khác biệt là gì. Ngoài ra tôi đã không nhận được những gì là ra xem mặt của đối tượng trong nó đề với quan điểm bên ngoài của một đối tượng.

Ai đó có thể đưa thêm ánh sáng vào điều này với một số ví dụ thực tế về cuộc sống hoặc với một số ví dụ có lập trình nếu có thể.

Trả lời

30

Trừu tượng là khoảng xác định các điểm chung và giảm các tính năng mà bạn phải làm việc với các cấp mã khác nhau.

ví dụ: Tôi có thể có một lớp học Vehicle. A Car sẽ lấy từ một số Vehicle, như một số Motorbike. Tôi có thể yêu cầu mỗi Vehicle số lượng bánh xe, hành khách, v.v ... và thông tin đó đã được trừu tượng hóa và xác định là phổ biến từ CarsMotorbikes.

Trong mã của tôi, tôi có thể thường chỉ đối phó với Vehicles qua phương pháp phổ biến go(), stop() vv Khi tôi thêm một loại xe mới sau này (ví dụ Scooter) đa số các mã của tôi sẽ vẫn mù tịt về thực tế này, và thực hiện các Scooter một mình lo lắng về các đặc điểm của Scooter.

65

OO Abstraction xảy ra trong thiết kế cấp lớp, với mục tiêu ẩn sự phức tạp thực hiện của cách các tính năng được cung cấp bởi một API/thiết kế/hệ thống được triển khai, trong một cảm giác đơn giản hóa 'giao diện' để truy cập triển khai cơ bản.

Quá trình này có thể được lặp lại ở mức độ cao hơn (lớp) trừu tượng, cho phép các hệ thống lớn được xây dựng mà không làm tăng độ phức tạp của mã và hiểu, ở các lớp cao hơn. Ví dụ, một nhà phát triển Java có thể sử dụng các tính năng cấp cao của FileInputStream mà không cần quan tâm đến cách hoạt động của nó (tức là xử lý tệp, kiểm tra bảo mật hệ thống tệp, cấp phát bộ đệm và bộ đệm sẽ được quản lý nội bộ và bị ẩn từ người tiêu dùng). Điều này cho phép thực hiện FileInputStream để được thay đổi và miễn là API (giao diện) thành FileInputStream vẫn nhất quán, mã được tạo dựa trên các phiên bản trước sẽ vẫn hoạt động.

Tương tự, khi thiết kế các lớp học của bạn, bạn sẽ muốn ẩn việc triển khai nội bộ từ những người khác càng nhiều càng tốt.

Trong định nghĩa Booch , OO Encapsulation đạt được thông qua Information Hiding, và đặc biệt là xung quanh che giấu dữ liệu nội bộ (trường/thành viên đại diện nhà nước) thuộc sở hữu của một cá thể của lớp, bởi thực thi truy cập vào dữ liệu nội bộ trong một kiểm soát cách thức, và ngăn chặn trực tiếp, thay đổi bên ngoài cho các lĩnh vực này, cũng như ẩn bất kỳ phương pháp thực hiện nội bộ của lớp (ví dụ bằng cách làm cho chúng riêng).

Ví dụ, lĩnh vực một lớp học có thể được thực hiện private theo mặc định, và chỉ khi truy cập bên ngoài để những được yêu cầu, sẽ một get() và/hoặc set() (hoặc Property) được tiếp xúc từ lớp. (Trong các ngôn ngữ OO hiện đại trong ngày, các trường có thể được đánh dấu là readonly/final/immutable để tiếp tục hạn chế thay đổi, ngay cả trong lớp học).

Ví dụ nơi NO ẩn thông tin đã được áp dụng (Bad Practice):

class Foo { 
    // BAD - NOT Encapsulated - code external to the class can change this field directly 
    // Class Foo has no control over the range of values which could be set. 
    public int notEncapsulated; 
} 

Ví dụ nơi lĩnh vực đóng gói đã được áp dụng:

class Bar { 
    // Improvement - access restricted only to this class 
    private int encapsulated; 

    // The state of Bar (and its fields) can now be changed in a controlled manner 
    public void setEncapsulatedField(int newValue) { 
     if (newValue < 100) { 
      encapsulated = newValue; 
     } 
     // else throw ... out of range 
    } 
} 

Ví dụ về bất biến/constructor- chỉ khởi tạo một trường:

class Baz { 
    private final int onlyValue; 

    public void Baz(int immutableValue) { 
     // ... can check that immutableValue is valid 
     onlyValue = immutableValue; 
    } 
    // Further change of `onlyValue` outside of the constructor is NOT permitted 
    // even within the same class 
} 

Re: Abstraction vs Abstract class

Abstract classes các lớp học mà thúc đẩy tái sử dụng tương đồng giữa các lớp, nhưng mà mình không thể trực tiếp được khởi tạo với new() - lớp trừu tượng phải được subclassed, và chỉ concrete (không trừu tượng) các lớp con có thể được khởi tạo. Có thể một nguồn gây nhầm lẫn giữa Abstractionabstract class là trong những ngày đầu của OO, thừa kế được sử dụng nhiều hơn để đạt được sử dụng lại mã (ví dụ: với các lớp cơ sở trừu tượng được liên kết).Ngày nay, composition is generally favoured over inheritance, và có nhiều công cụ có sẵn để đạt được trừu tượng, chẳng hạn như thông qua giao diện, sự kiện/đại biểu/chức năng, đặc điểm/mixins vv

Re: Đóng gói vs Thông tin Ẩn

Gần đây hơn encapsulation là thông thường cũng được sử dụng theo nghĩa chung hơn khi xác định phương thức, trường, thuộc tính, sự kiện et al cho bundle vào một lớp.

Trích dẫn Wikipedia:

Trong bối cảnh cụ thể nhiều hơn một ngôn ngữ lập trình hướng đối tượng, khái niệm được dùng để chỉ một cơ chế thông tin ẩn, một cơ chế đóng bó, hoặc sự kết hợp của cả hai.

Ví dụ, trong báo cáo kết quả "Tôi đã đóng gói mã truy cập dữ liệu vào lớp riêng của mình", việc giải thích của đóng gói là tương đương với các Separation of Concerns chính (chỉ số S trong RẮN), và có thể được sử dụng như một từ đồng nghĩa để tái cấu trúc.


[1] Một khi bạn đã nhìn thấy Booch của encapsulation cat picture bạn sẽ không bao giờ có thể quên đóng gói - p46 của Object Oriented Analysis và Thiết kế với các ứng dụng, 2nd Ed

+0

để API Java chúng tôi sử dụng là trừu tượng? – sras

+0

Vâng, ở mức độ cao, API cung cấp một trừu tượng đơn giản hơn cho người tiêu dùng để sử dụng, không biết gì về sự phức tạp cơ bản đằng sau thiết kế nội bộ của nó. Java rõ ràng là một ngôn ngữ, với nhiều khung công tác cao cấp liên quan. Tuy nhiên, tôi tin rằng cụ thể hơn, vào khoảng thời gian thiết kế OO [thuật ngữ hiệu trưởng] (https://en.wikipedia.org/wiki/Object-oriented_design) được đặt ra, sự trừu tượng đó cụ thể hơn đề cập đến thiết kế và phân tách cấp lớp , thay vì đề cập đến khung công tác hoặc thiết kế cấp doanh nghiệp. – StuartLC

40

Trong đơn giản words: Bạn trừu tượng hóa khi quyết định những gì cần thực hiện. Bạn đóng gói khi ẩn nội dung nào đó mà bạn đã triển khai.