簡體   English   中英

在C#中,有什么更好的替代方法來使用getter和setter?

[英]What are better alternatives to getters and setters in C#?

我看過一些關於面向對象編程和很多資源,如使用getter / setter方法的這個建議,他們應該是非常不經常使用。 該文章的引言說:

不要要求您進行工作所需的信息; 詢問具有該信息的對象為您完成工作。

雖然這在原則上聽起來不錯,但我不確定如何最好地實現這一點。 說我有一堂課描述一輛汽車。 在該類別中,可以說該類別中存儲的這款汽車的品牌是“豐田”。 現在,我有一個GUI,它想要顯示這是“豐田”。 沒有吸氣劑怎么辦?

即使我抽象出“ Toyota”作為字符串存儲並返回一個文本框,其中已寫有“ Toyota”,但這聽起來充其量不過是原始屬性的包裝形式的獲取器。 我只是認為諸如TextBoxes之類的東西應該只在GUI的類中,而不應該在我的car類之類的幫助器類中。

該文章描述了您應該使用方法而不是屬性獲取器/設置器。 基本上,這建議一種方法應執行操作來修改狀態,而不是允許設置器修改狀態。 例如,我可以開設一個帶有“月和日”屬性的課程。 然后,我可以有執行此操作的代碼:

obj.Day = 28;
obj.Month = Months.February;
obj.Day = 30;
obj.Month = Months.March;

一旦我將日期設置為30,而月份為2月,則狀態為無效。

文章建議類不應允許此類事情,而應提供執行特定操作的特定方法,例如:

obj.ChangeDate(Months.March, 30);

如果由於DateTime而使日期時間類比令人困惑,則可以使用經緯度坐標類似的示例:

obj.Latitude = 45.4112;
obj.Longitude = -75.6981;
//... 
obj.Latitude = 39.73;
obj.Longitude = -86.27;

當“緯度”設置為39.73時,該位置將成為Newark附近的位置,而不是渥太華(第一緯度/經度)或印第安納波利斯(第二緯度/經度)。 保留緯度/經度的設置會使接口處於無法驗證其不變性的開放狀態,並且有些人可能說不是真正面向對象的。 因此,您可能有一個方法代替:

obj.MoveTo(39.73, -86.27);

OO意味着封裝狀態和行為。 盡管某些屬性可能會“封裝”狀態,但通常不會。 它們將實現與接口分離開來,以便可以更改用作屬性的后備存儲的東西,但是很少這樣做。 因此,這些屬性只是在提供實現細節方面與提供公共字段不同。

有一些類似“命令查詢分離”的概念都建立在該思想的基礎上,建議接口應該更新狀態或查詢狀態,但不能同時更新狀態或查詢狀態。 帶有getter和setter的屬性提供了同時更新狀態和查詢狀態的接口。 上面的示例MoveToChangeDate將是“命令”。 從概念上講,您將提供其他查詢狀態的方法。 如果需要的話。

屬性的另一個問題之一是,人們僅僅因為它是一個屬性就習慣性地同時添加了吸氣劑和吸氣劑。 可能不需要獲得或設置屬性的能力,只需簡單地通過死記創建和接口同時添加getter和setter即可,而不需要進行測試和維護。

微妙? 當然; 但是他在談論的是面向對象的設計,而不是“有效”的代碼。

您將忽略“完成工作”。 如果您要完成的工作是汽車的品牌,則返回該品牌的吸氣劑即可完成工作。

文章的意思是,如果您希望對類數據進行處理,請將其放入類中。 不要從類中提取數據,對其進行處理,然后將其返回給類:

var c = new Car();
c.Odometer += 10;  // bad
c.DriveMiles(10);  // good

我也質疑該文章對C#的適用性。 它聲稱:

getter和setter方法(也稱為訪問器)很危險,其原因與公共字段很危險:它們提供了對實現細節的外部訪問。

在C#中,這是錯誤的,C#訪問器可以接受任意類,它們不“提供對實現細節的外部訪問”。

getter和setter並不是邪惡的,只是不應該為每個屬性自動生成它們。 就您的示例而言,一個Car類可能應該具有一個返回字符串的getBrand方法,但是可能不需要此屬性的設置方法。 Car中返回品牌名稱的TextBox的方法比返回字符串的簡單getter方法更糟糕,因為它不是很通用。

我現在可以看到Peter Ritchie的答案:changeDate的好例子。 Date類應該提供類似的方法,而不是提供日和月的getter,並且需要用戶代碼自行計算日歷中的第二天。

基本上,他的意思是說您有一個具有十個屬性的類,並且您想將其轉儲到一行csv中。 將Tocsv方法添加到類中以返回其中包含一堆csvs的字符串。 不要編寫通過屬性訪問它並構建csv字符串的其他類,因為它們必須緊密耦合。

不知道為什么要選出訪問器,問題在於它們與獲取和設置離散方法完全相同,或者更糟糕的是成員變量。

顯然有限制,您必須有充分的理由更換

SomeLabel.Text = SomeInstance.StringValue;

SomeInstance.MakeStringValueALabel(SomeLabel);

暫無
暫無

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

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