Access control, extern và forward class: tổ chức API có ranh giới
Tiên quyết
Sau bài này bạn sẽ
- Phân biệt local/protected với API public
- Tách extern declaration và implementation mà giữ đúng scope
- Dùng typedef class trước định nghĩa trong cùng source
Caller cần API thay vì sửa mọi field
Vault giữ secret và đếm updates cho derived class. Cho module sửa trực tiếp hai field làm mất ranh giới trách nhiệm. Example dùng method public để đọc secret, method derived để cập nhật counter và compiler để kiểm các truy cập bị cấm.
Local secret thuộc phần triển khai của Vault
Secret khai local và chỉ được gán trong Vault.new rồi đọc qua read_secret. Main gọi getter được 17, không đọc vault.secret trực tiếp. Derived class gọi API base cũng khác với tự truy cập member local của base.
Protected cho derived method, vẫn chặn caller ngoài
Updates khai protected. CountedVault.bump tăng nó, count trả giá trị để TB quan sát. Hai lần bump cho 2. Negative probes thử module đọc secret hoặc updates phải bị parser từ chối; không đổi member sang public chỉ để test compile.
Extern tách declaration khỏi body
Holder khai extern function int read_value();, body viết ngoài class bằng Holder::read_value. Nó vẫn là method của Holder và đọc item. Extern không tự biến method thành function tự do, không tìm source file bị thiếu hoặc thay namespace package.
Forward declaration chỉ báo tên class sẽ được định nghĩa
typedef class Data; cho Holder khai một handle Data trước khi body class Data xuất hiện. Tất cả nằm trong cùng source/file list của ví dụ. Forward declaration không tạo Data object, không cấp quyền truy cập private hoặc thay việc cung cấp định nghĩa hoàn chỉnh.
API vẫn cần chính sách cho handle chưa có object
Holder mới tạo có item=null, read_value trả sentinel-1 theo contract riêng. Sau khi gán item=new(12), method trả 12. Sentinel không phải cách biểu diễn chung của null hoặc rule ngôn ngữ; production API có thể cần status riêng để phân biệt giá trị hợp lệ.
Body ngoài class vẫn phải thực hiện đúng contract
Mutation trả item.value+1 bị symptom extern or access contract bắt. Access control không kiểm công thức hộ bạn; compiler chỉ ngăn một số truy cập bất hợp lệ. Tách kiểm quyền, null path và dữ liệu trả về.
Public API và ba phần tổ chức class
Expected trước chạy: empty-1, extern_value12, secret qua getter 17, protected_updates2. Main không claim mọi separate compilation, friend semantics hoặc mọi extern signature; negative parser probes được ghi riêng với diagnostic thực.
Tự kiểm tra
Ẩn dữ liệu cần bảo vệ, để API diễn đạt contract
Chọn local cho implementation detail, protected cho extension point thật sự cần ở subclass. Dùng extern/forward declaration để sắp xếp source rõ, không coi chúng là cách bỏ dependency. Test cả hành vi API và các truy cập compiler phải từ chối.
Nguồn và mức độ đối chiếu
- SystemVerilog local vs protected — bản chụp resources.zip, Nguồn đào tạo đã đọc. Trích dẫn; nguồn đã đọc các mục liên quan.
- Thí nghiệm nguyên bản ex.b5.access, Bằng chứng thực nghiệm. Trích dẫn; nguồn đã đọc toàn văn.
- IEEE 1800-2023 SystemVerilog LRM, Class handles, inheritance, virtual methods, access and parameterization. Chưa đối chiếu với văn bản nguồn (chưa mở).
- Thí nghiệm nguyên bản ex.b5.access, Source, self-checks, verification.json và mutation/capability probes. Trích dẫn; nguồn đã đọc toàn văn.
- SystemVerilog local vs protected — bản chụp resources.zip, Accessing a local Member From Outside the Class; Accessing a local Member From a Child Class; Accessing a protected Member From Outside the Class; Accessing a protected Member From a Child Class. Trích dẫn; nguồn đã đọc các mục liên quan.
- SystemVerilog 'extern' — bản chụp resources.zip, Basic Syntax. Trích dẫn; nguồn đã đọc các mục liên quan.
- SystemVerilog Typedef Class — bản chụp resources.zip, The Problem: A Chicken-and-Egg Reference; The Fix: Forward Declaration With typedef. Trích dẫn; nguồn đã đọc các mục liên quan.