2012-01-17 35 views
7

Mã dụ:Bạn có nên bảo vệ các trường không?

unit Foo; 

    TFoo = class 
    protected 
    FList: TList; // Lifetime is managed by constructor and destructor 
    public 
    property List: TList read FList; 
    constructor Create; 
    destructor Destroy; override; 
    end; 

unit Bar; 

    TBar = class(TFoo) 
    procedure MyMethod; 
    end; 

procedure TBar.MyMethod; 
begin 
    // Access of FList goes here 
end; 

Lớp TBar có thể trực tiếp thay đổi giá trị của FList, nhưng đó không phải là thực sự cần thiết, vì nó chỉ có để gọi các phương thức của nó/sử dụng thuộc tính của nó.

Tôi có nên đặt FList ở chế độ riêng tư và sử dụng thuộc tính để truy cập từ TBar thay thế không?

Bạn xử lý các trường hợp như thế nào? Có cân nhắc về hiệu suất nào không?

+0

Điều này có phần liên quan đến http://stackoverflow.com/questions/8281582/using-properties-instead-of-fields-in-class-methods-of-the-same-unit-is-a-bad- pr, nhưng cụ thể hơn. –

+1

* Vô số lần * Tôi đã đánh thứ gì đó sẽ làm giảm công việc của tôi nếu điều đó không được riêng tư. Tôi tin rằng nhiều người khác cũng đã làm kể từ khi tôi đã nhìn thấy các nhà phát triển hoàn toàn bỏ qua * tư nhân * và sử dụng * bảo vệ * như phạm vi nghiêm ngặt nhất. +1 –

+2

@Sertac Đó thường là vấn đề nhất khi bạn không có quyền kiểm soát mã khác. Khi bạn có toàn quyền kiểm soát tất cả mã, bạn có thể sử dụng 'riêng tư 'hoặc thậm chí là' riêng tư nghiêm ngặt' và khi điều đó trở nên quá hạn chế, bạn có thể thư giãn các hạn chế khi cần. –

Trả lời

3

Mặc dù tôi đồng ý rằng bạn có thể bắt đầu với đặc quyền ít nhất, và di chuyển mọi thứ trong tầm nhìn khi cần thiết, nó chỉ vì nó kết thúc việc tạo ra thiết kế hướng đối tượng phù hợp mà không cần phải suy nghĩ quá chức năng kinh doanh thực tế cần được tiếp xúc.

Bạn nên đóng gói và ẩn càng nhiều sự phức tạp càng tốt trong một đối tượng để giao diện bên ngoài càng nhỏ gọn càng tốt. Một cách để thực hiện điều này là chỉ thêm hoặc hiển thị các thuộc tính khi bạn cần chúng.

Nếu bạn không cần truy cập bên ngoài vào một thành viên cụ thể của lớp, nó có thể chỉ đơn giản là tạo tác triển khai và không phù hợp với việc sử dụng thực tế của lớp. Do đó, sự phức tạp nên được ẩn đi.

Trong trường hợp này, vì TBar kế thừa từ TFoo, Được bảo vệ là mức hiển thị hợp lệ, vì nó được dành riêng cho các lớp kế thừa. Ngoài ra, bởi vì TBar được thừa hưởng từ TFoo, có lẽ bạn đang nghĩ rằng nó sẽ có một số đặc quyền bổ sung cho các hoạt động bên trong của TFoo bởi vì nó là, sau khi tất cả, lớp con của nó. Tại sao chúng ta nên xuống hạng TBar để có cùng cấp truy cập thấp như các lớp khác?

Câu trả lời phụ thuộc vào việc FList là một thành viên lớp thực tế của TFoo, khi chúng ta xem xét mô hình TFoo đại diện, hoặc cho dù đó chỉ là chi tiết triển khai. Ngoài ra, mức truy cập yêu cầu là bao nhiêu? Chúng ta chỉ đơn giản là truy cập nó, hay chúng ta đang thay đổi việc thực hiện?

Tôi đoán rằng bạn không cần quyền truy cập vào FList và bạn không thay đổi việc triển khai, trong trường hợp đó, ngay cả khi hai lớp học trong cùng một đơn vị, tôi vẫn đặt FList Private over Protected .

Nếu bạn chỉ truy cập vào thành viên lớp học từ các lớp con cháu trong cùng một đơn vị, tôi sẽ vẫn giữ riêng tư. Tuy nhiên, nếu FList là thứ bạn cần ghi đè trong TBar (có thể không phải vì nó không phải là một phương thức), hoặc được thiết kế như thứ gì đó thừa hưởng các lớp nên hoặc sẽ ghi đè, cho dù nó nằm trong cùng một đơn vị hay không , sau đó bạn sẽ muốn làm cho nó được bảo vệ.

Bạn cũng sẽ cần nâng cao khả năng hiển thị thành Được bảo vệ nếu bạn cần truy cập FList từ các lớp con cháu bên ngoài cùng một đơn vị.

+1

Cũng không có vấn đề gì nếu bạn tạo các trường của TFoo riêng tư hoặc được bảo vệ, chúng vẫn có thể nhìn thấy từ TBar, nếu TBar được khai báo trong cùng một đơn vị. Để tránh điều đó, trong hầu hết các phiên bản delphi gần đây sử dụng "nghiêm ngặt tư nhân". Trong Delphi 2007 không có 'Strict Private', di chuyển TBar đến đơn vị riêng của nó, để ngăn chặn" tình trạng người bạn tiềm ẩn của các lớp trong cùng một đơn vị "mà ObjectPascal/Delphi đã xây dựng trong thiết kế OOP của nó. –

+0

Nếu 'FList' là riêng tư (và không tiếp xúc với phạm vi công khai) và' TFoo' và 'TBar' nằm trong các tệp khác nhau, bạn có sử dụng thuộc tính được bảo vệ để truy cập nó từ' TBar' không? –

+0

@Jens, vâng. Với Protected, các lớp kế thừa có thể truy cập nó từ một đơn vị khác, trong khi vẫn ẩn nó khỏi các lớp khác. Nếu nó ở cùng một đơn vị, tôi rất có thể sẽ giữ nó ở chế độ riêng tư nếu tôi chỉ đơn giản truy cập vào nó, nhưng nếu tôi thay đổi việc thực hiện, tôi sẽ công khai nó. –

Các vấn đề liên quan