簡體   English   中英

您(幾乎)總是在類中實現哪些方法和接口?

[英]What methods and interfaces do you (almost) always implement in classes?

您始終在類中實現哪些方法和接口?

您是否總是重寫equals()? 如果這樣做,您還會做hashcode()嗎? toString()? 您是否養成了實施Comparable接口的習慣?

我剛剛編寫了一些代碼,在其中我需要實現compareTo()和重寫equals(),以使我的程序以理智的方式工作; 我現在開始看到在任何地方使用這些方法的方式...

你們怎么想?

除非需要,否則我通常不會提前實施。

如果我的類包含數據成員,並且我計划將其存儲在某個位置,則通常將實現equals,hashCode和同類對象。

但是,我發現我的大多數班級都沒有這個問題,因此沒有必要這樣做。 例如,如果您的課程圍繞其他對象而不是數據的功能展開,為什么要麻煩呢? 如果您有一個實例或按層次結構組織(例如,GUI小部件或窗口),為什么要打擾?

不要實現不需要的東西,但是請務必確保檢查是否需要它們,因為Java通常不會警告您。

另外,請確保使用您的IDE或類似Apache commons的東西來生成這些功能。 幾乎不需要手動編碼它們。

至於toString,我很少實現它,直到發現自己需要調試並且需要在Eclipse調試器中進行更好的展示(例如,代替對象ID)。 我擔心隱式轉換,並且在生成輸出時從不使用toString。

(幾乎)總是toString()

通常對於調試目的很有幫助。

如果重寫equals ,則(幾乎總是)必須重寫hashCode hashCode的約定是,兩個相等的對象必須具有相同的哈希碼。 如果您覆蓋equals,使得equals基於除系統標識哈希碼之外的其他內容,則兩個對象可能彼此相等,但具有不同的哈希碼。

我認為您永遠都不要實現不需要的東西,或者不確定是否需要它們。 如果它不能為您的代碼增加價值,請不要使用它。如果您想使您的(單元)測試與您的代碼保持同步,並使用它們顯示您的代碼用例,那么您不應有那些測試未涵蓋的內容。 這包括equals(),hashCode(),compareTo()等。

除了可能浪費時間外,我看到的問題是它會使讀取代碼的人感到困惑。 “為什么要實現該類的equals?它有一些數據值嗎?可以作為集合的一部分嗎?比較此類的實例是否有意義?”

因此,我想說的是只有在您真正需要它們時才實施它們。 因此,我不能說我總是實現這種方法。 也許toString()將是我編寫最多的方法,因為它在調試中很有用。

幾乎總是toString(),調試和閱讀有關對象Class @ 123456的內容很痛苦

必要時可以返回equals()和hashCode(),但必須兩者都選或都不選。

Iterable接口在類似於集合的類上很有用,並且通常只會返回諸如innerCollection.iterator()之類的東西。 可比性也可能有用。

此外,我們公司還創建了一些我經常使用的接口,例如Displayable(例如toString,但提供了更多或其他類型的信息,例如用於日志記錄)和ParseLocatable(用於來自我們解析的文件的內容,我們希望在其中查看例如,哪個文件和哪一行定義了特定規則(有點類似於stacktraces)

有效的Java一章介紹了如何以及何時實現toString,equals,hashCode,Comparable等。強烈建議閱讀。

我還發現自己大量重寫了ToString()方法。 特別是在開發過程中。 盡管代碼生成器有幫助,但是每次重命名類成員時都必須更改它,這很煩人。 其實我很生氣,我試圖找到一種補救辦法,這就是我想出的:

創建此格式的字符串:MemberType MemberName = MemberValue

用法:

string testMember = "testing";

Console.WriteLine(Member.State(() => testMember));

將'string testMember =“ testing”'寫入控制台。 這里是:

public static class Member
{
    public static string State<T>(Func<T> expr)
    {
        var member = ExtractMemberFromLambdaExpression(expr);

        Type memberType = GetTypeOfMember(member);

        string contents = ExtractContentsFromLambdaExpression(expr);

        return string.Format("{0} {1}={2}",memberType.Name,  member.Name, contents);
    }

    static string ExtractContentsFromLambdaExpression<T>(Func<T> expr)
    {
        if (expr() == null) {
            return "NULL";
        }

        string contents = string.Empty;
        if (expr().GetType().IsArray) {
            foreach (var item in (expr() as Array)) {
                contents += item.ToStringNullSafe() + ", ";
            }
            contents = contents.Trim().TrimEnd(',');
        } else {
            contents = expr().ToString();
        }

        return contents;
    }

    static MemberInfo ExtractMemberFromLambdaExpression<T>(Func<T> expr)
    {
        // get IL code behind the delegate
        var il = expr.Method.GetMethodBody().GetILAsByteArray();
        // bytes 2-6 represent the member handle
        var memberHandle = BitConverter.ToInt32(il, 2);
        // resolve the handle
        return expr.Target.GetType().Module.ResolveMember(memberHandle);
    }


    static Type GetTypeOfMember(MemberInfo member)
    {
        Type memberType;
        if (member.MemberType == MemberTypes.Field) {
            memberType = GetFieldType(member as FieldInfo);
        }
        else if (member.MemberType == MemberTypes.Property) {
            memberType = GetPropertyType(member as PropertyInfo);
        }
        else {
            memberType = typeof(object);
        }
        return memberType;
    }

    static Type GetFieldType(FieldInfo fieldInfo)
    {
        return fieldInfo.FieldType;
    }

    static Type GetPropertyType(PropertyInfo propertyInfo)
    {
        return propertyInfo.PropertyType;
    }
}

在我的博客中可以找到關於以下內容的更全面的解釋以及如何使用它: Generic ToString()方法

當您懶於編寫單元測試時, toString()有時對於測試目的確實很有幫助,在調試時也很方便觀察

但是我不建議在每個對象中都實現Comparable ,有時候會很好,但是明智地使用它會導致您實際上並不需要很多代碼。

同理toString()及其在不同語言和運行時中的變體,但我也想向您介紹Ned Batchelder的有關字符串化的文章,該文章不錯,很接近我的推理。

對於商業CRUD應用程序,我總是重寫ToString。 這有助於將List(Of T)綁定到WinForm控件。 例如,在將List(Of Customer)綁定到ListBox控件時,覆蓋Customer對象中的ToString以返回_name會自動顯示客戶名稱值。 派上用場。

我通常實現compareTo方法以及toString方法。 通常,知道該類的一個實例與另一個實例進行排序和搜索的方式比較好。 另外,重寫的toString方法也非常適合調試。 您可以看到對您編寫的類有意義的類內容(不僅僅是內存位置)。

在主要用於保存數據的對象(“岩石”)上,我發現toString和equals / hashcode契約是無價的。 這是因為岩石通常總是一直傳遞到集合中或從集合中提取出來,最顯着的是Hash(Set / Map)集合,這需要使用equals和hashcode協定,並且如果toString,則很容易在調試器中看到這些對象被實施。 在實現toString時,我總是使用Apache Common的ToStringBuilder類來顯示我的所有屬性-這樣,讀取輸出就非常容易。 我從不擔心“隱式轉換”-toString並不用作人類可讀的字符串,toString可以用於Number子類以進行來回轉換,實際上只是一個怪癖,等等。生產代碼應該永遠不要依賴toString方法將對象轉換為字符串表示形式,因為這不是它的用途-它是用於人類可讀的字符串表示形式,因此,如果非人類的但計算機代碼可用的字符串表示形式應定義為另一種方法想要的。

對於數據值類,我有一個AbstractPojo類,該類使用反射來實現equals,hashCode,toString和asMap()

我為所有我的數據值對象擴展了此類,因此不必每次都實現。

我沒有覆蓋ToString,但是有時我會應用DebuggerDisplay屬性,該屬性出於調試目的而相同,並且不會在發行版上增加開銷。

暫無
暫無

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

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