C ++のtypedefキーワードに相当するJavaや方法はありますか?


244

CおよびC ++の経歴を持っているので、の賢明な使用typedefが非常に役立つことがわかりました。Javaメカニズム、パターン、その他の効果的な方法など、Javaで同様の機能を実現する方法を知っていますか?


6
typedefは、良いものも悪いものも使用できますが、誰もがどちらに使用するかについては同意しません。typedefのどの側面が価値があると思いますか?そうすれば、Javaで同様の効果を得る方法や、Javaでしたくない理由を伝えることができます。以下の回答のコレクションは、著者のお気に入りの(または最も嫌いな)使用について話していることを前提としています。
PanCrit 2009

3
後でクラスに変換する可能性がある場合は、ネイティブ型をtypedefするのが好きです。typedef IndexT int; 例えば。その後、IndexTをクラスにしたい場合は、それを実装してtypedefを削除するだけです。情報を隠すのに役立ちます。
JRローホーン2010


1
これの欠点は何かpublic interface ScopeFactory { <Scope extends Map<String, Object>> Scope create(...) throws Exception; }
わかり

2
Scalaが好きかもしれませんstackoverflow.com/a/21223102/203968
oluies

回答:


112

Javaにはプリミティブ型、オブジェクト、配列があり、それだけです。typedefはありません。


37
ほとんどの人はtypedefに再定義booleanしたいと思いboolます。
トマーシュZato -復活モニカ

66
@TomášZatoほとんどの人は知りませんが、私の経験では、次のようなセマンティクスを追加するのに役立ちtypedef int PlayerIDます。これにより、コンパイラーはPlayerIDが他のintと互換的に使用されていないことを確認でき、人間にとってコードがはるかに読みやすくなります。基本的に、それは列挙型のようなものですが、値のセットが制限されていません。
weberc2 2015年

76
@TomášZatoなどの長い型を短くすることも便利typedef MegaLongTemplateClass<With, Many, Params> IsShorten;です。
Alex Medveshchek 2015

32
@ weberc2 "これにより、コンパイラはPlayerIDが他のintと互換的に使用されていないことを確認できるようになります" – typedefそのようなことを有効にしません。型に別の名前を付けるだけです。
emlai

7
たとえば、あるタイプのIDがintあり、それをに変更する必要longがある場合、IDを操作するコードのすべての場所で変更する必要がある場合にも役立ちます。があった場合はtypedef、1か所で変更するだけで済みます。
Jardo

101

これがあなたの言いたいことであれば、typedefしたいクラスを単に拡張することができます。例えば:

public class MyMap extends HashMap<String, String> {}

5
私は、これは任意のより多くのアンチパターンCでのtypedefを使用するよりもであるかどうかを主張するだろう
ゼッド

22
それは間違いなくです- typedef記事がそれらの偽のクラスについて説明している問題はありません(そしてそれらは非常に現実的です)。
Pavel Minaev 2009


7
私はtypedefが好きなのと同じ理由でこれが好きです。オブジェクトのコンテナがある場合、typedefを変更することでコンテナタイプを簡単に交換できます。また、コンテナをエンドユーザーに抽象化することもできます(これが望ましい場合もあります)。私は通常、これを別のクラスの内部で行うため、型がより明確になります(つまり、クラスBranchesがHashSet <MyTree> {}を拡張するMyTree.Branches)
Josh

8
メインのこのアプローチの問題は、あなたがそれを使用することができないということであるfinalクラス。
AJMansfield 14

14

1.6の時点ではJavaにtypedefはありません。最終クラス(Integer、Doubleなど)をサブクラス化できないため、実行できることは、目的のラッパークラスを作成することです。


3
参照されているアンチパターンの記事は、タイピングを短くしたいという前提に基づいています(これにより、実際に役立つタイプ情報が非表示になります)。ほとんどの人が望む実際の用途は、型を明確にし、コンパイラにその仕事を任せることです。上記のIndexTを参照してください。public Invoice fetchInvoiceItem(String、String、String); 対公共の請求書fetchInvoiceItem(CustomerId、InvoiceId、InvoiceLineItemId); 明示的な型とコンバーター/バリデーターにより、すべてが文字列として始まるWeb APIのプログラミングがはるかに安全になります。
englebart 2017年

Javaではオーバーロードする演算子がないため、醜くなります
mils

9

他の人が以前に述べたように、
Javaにはtypedefメカニズムはありません。
私は一般に「偽クラス」もサポートしていませんが、ここでは一般的な厳密な経験則はありません。
たとえば、コードで「ジェネリックベースの型」を何度も繰り返し使用する場合は、次のようになります。

Map<String, List<Integer>> 

あなたは間違いなくその目的のためにサブクラスを持つことを考慮すべきです。
たとえば、次のような減速をコードに含めることもできます。

//@Alias Map<String, List<Integer>>  NameToNumbers;

次に、コードでNameToNumbersを使用し、プリコンパイラタスク(ANT / Gradle / Maven)を使用して、関連するJavaコードを処理および生成します。
この回答の読者の一部にとってこれは奇妙に聞こえるかもしれませんが、これはJDK 5より前の「注釈」を実装したフレームワークの数であり、これがロンボクが行うプロジェクトやその他のフレームワークです。


5

本当に、Javalandに引き継がれるtypedefの唯一の使用法はエイリアスです。つまり、同じクラスに複数の名前を付けます。つまり、クラス「A」があり、「B」が同じものを参照するようにします。C ++では、「typedef BA;」を実行します。

残念ながら、彼らはそれをサポートしていません。ただし、関係するすべてのタイプを制御する場合は、ライブラリレベルで厄介なハックをプルできます。AからBを拡張するか、BにAを実装させることができます。


14
持つことtypedefも、ジェネリック型の呼び出しのためのエイリアスを作成することは有用であろう。例:(typedef A<Long,String> B;これはあなたが説明したことの特別なケースかもしれませんが、それはアイデアの魅力をもう少しはっきりと示しています)。
igorrs

私の使用例では、プリミティブ型にエイリアスを与えたいと思います。real_tdoubleboolのためにboolean
アーロンフランケ

3

おそらく、これは別の可能な置換である可能性があります:

@Data
public class MyMap {
    @Delegate //lombok
    private HashMap<String, String> value;
}

2
myMaptypeのインスタンスを定義するときはいつでもMyMap、のmyMapInstance.value.SomeOperation()代わりに入力するだけで実際のHashMapを操作できるため、これには問題があると思いませんかmyMapInstance.SomeOperation()。面倒ですよね。
mercury0114 2016年

2
まだmyMapInstance.SomeOperation()を実行できます-これが@Delegateの目的です
shrewquest

3

他の回答で述べたように、疑似typedefアンチパターンを回避する必要があります。ただし、typedefは、それを実現する方法ではない場合でも有用です。同じJava表現を持つ異なる抽象型を区別したい。パスワードである文字列と住所である文字列、またはオフセットを表す整数と絶対値を表す文字列を混同したくない場合。

チェッカーFrameworkは下位互換性のある方法でのtypedefを定義することができます。などのプリミティブクラスやのようなint最終クラスでも機能しStringます。実行時のオーバーヘッドがなく、同等性テストを中断しません。

Checker Frameworkマニュアルのセクションタイプエイリアスとtypedefsでは、必要に応じてtypedefを作成するいくつかの方法について説明しています。




-6

Enumを使用することもできますが、限定された値のセットしか許可されないという点で、typedefとは意味的に少し異なります。別の可能な解決策は、名前付きラッパークラスです。

public class Apple {
      public Apple(Integer i){this.i=i; }
}

しかし、特にクラスがエイリアス以外の機能を持たないことがコードから明らかでない場合、これははるかに不格好に思えます。


-7

Typedefを使用すると、アイテムを暗黙的に割り当てられていないタイプに割り当てることができます。一部の人々は拡張機能でこれを回避しようとします。これが悪い考えである理由の説明については、IBMでここを読んでください。

編集:強力な型推論は便利なものですが、typedef管理された言語で醜い頭を育てるのは(決して?)

編集2:C#では、ソースファイルの先頭で次のようなusingステートメントを使用できます。表示されている2番目の項目を実行する必要がないように使用されます。名前の変更が表示されるのは、スコープが2つのタイプ間で名前の衝突を引き起こしたときだけです。名前の変更は1つのファイルに制限されており、そのファイルの外では、そのファイルを使用したすべての変数/パラメーターの型がフルネームで認識されます。

using Path = System.IO.Path;
using System.IO;

23
「typedefを使用すると、アイテムを暗黙的にタイプではないタイプに割り当てることができます」何ですか?Typedefでは、単に型のエイリアスとして別の名前を作成できます。タイプはまったく同じですが、短い名前になります。型推論とは何の関係もありません。-1
2009

@jalf:実際、型推論はあなたが話していることの正確な解決策として使用されますが、「typedef」を使用して名前の衝突を回避できる別の例を示しました。
サムハーウェル


@AlexanderMalakhovありがとう、私は先に進み、あなたのリンクで答えを更新しました
デイブ・マクレランド

-14

Javaではtypedefは必要ありません。プリミティブ以外はすべてオブジェクトです。ポインタはなく、参照のみです。通常typedefを使用するシナリオは、代わりにオブジェクトを作成するインスタンスです。


19
いいえ、型の名前を短くしたい場合は、typedefが必要です。または、ソースコードのある場所を変更することで、あるタイプの使用を別のタイプに置き換えることができるようにしたい場合だけです。
2009

28
@Bill K:えっと、std :: map <int、std :: map <std :: string、boost :: shared_ptr <std :: string>>> :: const_iterator a少しだけ。その場合、名前を短くするtypedefは読みやすさを向上させますが、妨げることはありません。
ジョエル

22
タイプの名前を変更すると、読みやすさが大幅に向上します。何が読みやすく、理解しやすい(したがって、より読みやすい:) UnmodifiableDirectedGraph<IncrediblyFancyEdgeType, IncrediblyFancyAbstractNode.EvenFancierConcreteNode>か、またはIncrediblyFancyGraph?私はいつでも定義を参照して、それが実際に何であるかを知ることができます。そうすればUnmodifiableDirectedGraph<IncrediblyFancyEdge,IncredilyFancyAbstractNode.SlightlyLessFancyConcreteNode>、退屈を逃さないようにすることもできます。
Aleksandar Dimitrov

10
@AleksandarDimitrov私はこれを入力してコメントがほぼ3年前であることを知っていますが、その例がどれほど不自然で非現実的であるかを指摘することは非常に重要だと思いEnterpriseます。
ケーシー

4
悪い名前は読みやすさを妨げます。良い名前が役立ちます。Typedefsは、完全な名前が長すぎてコードのフォーマットが読みにくくなったり、失敗したりする場合に役立ちます。また、他の誰かの不十分に選択された、またはあいまいなクラス名と対話するときにも役立ちます。typedefが本質的にコードを読み取り不可能にすると確信している場合は、importステートメントを使用してはならず、常に完全修飾クラス名を参照する必要があると考えてください。
クリストファーバーバー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.