簡體   English   中英

導出和銷毀封裝,還是違反 DRY?

[英]Derive & Destroy Encapsulation, or Violate DRY?

我有兩個 C++ 類: Sequence ,就像std::vectorFile ,它是代表機器上文件的字符串Sequence

Sequence派生File是不費吹灰之力的。 它的行為完全相同,但增加了讀取和寫入文件的功能。 File特定的功能很容易實現,無需將Sequence的數據成員標記為受保護。 相反,它們可以是私有的,並且File可以使用Sequence的公共接口。 到處都是快樂的時光。

我想制作一個內部管理動態分配的 memory 的Array class。 無法調整Array object 的大小; 大小在構造函數中指定。*

這就是事情變得有爭議的地方。

從概念上講,從Array派生Sequence是有意義的。 就像File是一個具有讀取和寫入文件的附加功能的Sequence Sequence一個具有按需調整大小的附加功能的Array

但有一個關鍵區別:調整大小功能需要直接訪問正在管理的 memory Array 換句話說,以前的私有成員現在必須受到保護。

使用受保護成員而不是私有成員會破壞封裝。 ArraySequence之間的鏈接是唯一需要它的鏈接; 作品中的其他類可以只使用它們父母的公共接口。 從這個意義上說,推導是個壞主意。

您可能會爭辯說,想要 arrays 的人可以只使用Sequence並忽略調整大小的功能。 但是話又說回來,您可以只使用File並忽略讀/寫功能。 這就像購買一台筆記本電腦,但從未將其從辦公桌上移開。 這根本沒有意義。

最好的舉措是什么:派生並可能破壞封裝; 使Array成為一個完全獨立的 class,並且必須毫無意義地重新實現很多功能; 還是完全忘記Array而只是讓人們使用Sequence

*請注意,這是一個娛樂和教育項目,因此具有不可調整大小的動態分配數組的實用性無關緊要。

您可能會考慮將問題切入稍微不同的方向。 而不是 inheritance,也許這個問題可以用一個模板來解決——具體來說,一個管理集合緩沖區的策略模板。 您將擁有(至少)兩種實現方式:一種用於固定分配,另一種用於自動調整大小。

這根本不會破壞封裝,而且我可以看到兩者之間幾乎唯一的重疊是初始分配可能大致相同,無論是固定的還是可變的。 鑒於這是多么微不足道,我懷疑是否值得花費大量時間或精力來嘗試將其排除在外。 理論上可能是這樣,但至少在典型情況下,我們談論的是一行代碼,而且是非常簡單的一行代碼。

暫時回到 inheritance 問題,歸結為:這非常類似於標准圓形與橢圓形的情況,其中一個看起來像另一個,但最終兩者都不滿足 LSP - 你不能安全地將任何一個視為另一個,因此(至少是公開的)inheritance 不適合。 私有 inheritance 不需要遵循 LSP,但通常僅在/如果您需要/想要覆蓋基類的虛擬 function 時有用,這在這里似乎也不太可能。

我不會在這里使用推導。

Sequence並不是真正的Array 雖然實際上它們似乎有許多常用方法,但從設計的角度來看,它們有非常不同的用途和保證。

但是,在Sequence中使用Array並讓Sequence直接將多個調用(內聯)轉發到Array是有意義的:

template <typename T>
class Sequence
{
public:
  Sequence(): _array(10) {}
  explicit Sequence(size_t n): _array(n) {}

  bool empty() const { return _size == 0; }
  size_t size() const { return _size; }
  size_t capacity() const { return _array.size(); }

private:
  size_t _size; // current size
  Array<T> _array;
}; // class Sequence

注意:我在這里假設 Array 是同時使用其所有元素構建的,而序列將一次添加一個

同樣, FileSequence派生是否有意義? 您是否沒有實現問題,例如將Sequence的內容與磁盤表示同步?

好吧,在您的情況下,使用公共inheritance 從Array派生Sequence絕對是個壞主意(從矩形派生正方形)。 就面向對象編程而言,Sequence IS NOT an Array,因為Array具有Sequence所沒有的屬性,它是: An Array object cannot be resized 如果進行推導,就會破壞Liskov 替換原則

在您的情況下,由於您想要實現一些功能,已經存在於另一個 class 中,我建議您使用私有inheritance (這意味着 inheritance 的實現),或存儲Sequence的私有區域組合和例如Array將其用於內部實現。

UPD:但是,在我看來,使用Array實現Sequence也很成問題。 也許最好創建一些抽象的基礎 class Container來實現SequenceArray的通用功能,然后從中派生這兩個類。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM