1 Javaのための暗黙的に型定義される 構造体 大久保 貴司 千葉 滋 東京工業大学 数理・計算科学専攻 2 静的型付け言語における構造体の利用 • 構造体(レコード型) ▫ 複数の異なる型のデータを まとめるために利用 Java 人を表す構造体を 利用したい • 静的型付け言語における構造体 ▫ 定義が別途必要 クラス等 ▫ 構造体は単純なデータ構造 値の出し入れさえできれば良い メソッドや関数は必要ない class Person{ String name; int age; } Person p = new Person(); p.name = “hoge”; p.age = 20; 3 構造体の定義は省略したい • 局所的にしか利用しない場合 • タプルの利用 ▫ 新たな定義なしに生成可能 ▫ 構造体として扱う上での制限 任意の数のメンバをもつタプルは簡潔に記述できない 各メンバへのアクセスは名前でなく index等 不可変 Scalaのタプル val p = (“hoge”, 20) // p : Tuple2[String, Int] 4 動的型付け言語なら可能 • オブジェクトの型を定義する必要がない ▫ オブジェクトのメンバ (プロパティ) は自由に追加可能 • 動的型付け言語だからできる記述法 ▫ 静的型付け言語 にこのまま導入することは不可能 Java JavaScript class Person{ String name; int age; } Person p = new Person(); p.name = “hoge”; p.age = 20; 定義する必要なし var p = {}; p.name = ”hoge”; p.age = 20; 5 提案: 暗黙的に型定義される構造体 • 動的型付け言語のような構文で構造体を利用可能 ▫ Javaで実現 ▫ ストラクトオブジェクトと var 型を導入 メンバを自由に追加可能 追加したメンバにはアクセス可能 • フィールド以外で利用可能 本システムを用いた Java var 型: ストラク トオブジェクトを 参照する変数 の宣言時の型 var p = new(); p.name = “hoge”; p.age = 20; int i = p.age; ストラクトオブジェ クト( 構造体を表す オブジェクト)を生 成 6 暗黙的な型定義 • structural type [Cardelli ‘88]+ 型推論 ▫ 型はstructural type を用いて表現 型は内部のデータ構造によって区別される 型 = アクセス可能なメンバの集合 ▫ 変数の型推論 構造体のメンバへの代入から適切な型を決定 変数が定義されているメソッド内をパース 変数 p の型 Struct{ String name; int age; } var p = new(); p.name = “hoge”; p.age = 10; 20; int i = p.age; 7 構造体のフィールドの型 • 構造体のフィールドへ異なる型のオブジェクトが代 入されている場合 ▫ フィールドの型 = 代入される各オブジェクトの型のアッ パーバウンドの型 変数 a の型 Struct{ Shape obj; } class Shape{…} class Circle extends Shape{…} class Square extends Shape{…} var a = new(); a.obj = new Circle(); a. obj = new Square(); 8 Subtyping • new()によって初期化されていないvar 型の変数へ 既存のストラクトオブジェクトを代入 ▫ 必要に応じてスーパータイプを生成 共通のアクセス可能メンバのみメンバとして持つ new()で 初期化 var circle = new(); circle.color = “red”; circle.radius = 3; new()で 初期化 var square = new(); square.color = “blue”; square.size = 5; 代入 var shape; shape = circle; shape = square; struct{ String color; int radius; } struct { String color; int size; } Struct{ String color; } circleの型 squareの型 shapeの型 9 メソッドへの受け渡し(1) • ストラクトオブジェクトをメソッドに渡すことが可能 ▫ メソッドの仮引数の型にvar型を指定 ▫ 仮引数の型 = 仮引数がメソッド内で満たすべき条件 を満たす型 ▫ 簡単な記述のみ可能 (現在) 仮引数xの型 void f(var x){ String s = x.name; int age = x.age; : } Struct{ String name; int age; } var p = new(); p.name = “hoge”; p.age = 20; f(p); pがxのサブタイプ であれば引数としてOK 10 メソッドへの受け渡し(2) • ストラクトオブジェクトをメソッドの返り値とすることが 可能 ▫ メソッドの返り値の型としてvar型を指定 var makePerson(){ var p = new(); p.name = “hoge”; p.age = 20; return p; } var person = makePerson(); makePerson, person共に 以下の型がつけられる Struct{ String name; int age; } 11 typeof の提供 • 型を取得するための演算子 ▫ 本システムでは構造体の型の名前を明示的に指定で きないため必要 p と同じ型のストラ クトオブジェクトの み格納可能 var p ; Map<String, typeof(p)> map = new HashMap<String, typeof(p)>(); for(int i = 0; i < 5; i ++){ p = new(); p.name = “hoge” + i; p.age = 10; map.put(“p” + i, p); } Struct{ String name; int age; } p の型 12 実装 • 標準のバイトコードに変換 ▫ var 型 = Object 型 変数ごとにインタフェースを作成、必要に応じてキャスト インタフェースがアクセス可能なフィールドを表す ▫ ストラクトオブジェクト 上記のインタフェースを実装するクラスのインスタンス ストラクトオブジェクトを 表すクラス 変数の型 interface StringName{ String getName(); void setName(String name) } class Var$$0 implements StringName{ String name; String getName(){return name;} void setName(String name){ this.name = name;} } 13 実験 • 内部クラスによる構造体と本システムを比較 ▫ 構造体を生成・操作するメソッドを100個定義し、実行 するプログラム ▫ コンパイル時間と実行時間を計測 内部クラスを用いた構造体 run(){ class Person{…} Person p = new Person(); p.name = “hoge”; p.age = 5; : } 本システムを用いた構造体 run(){ var p = new(); p.name = “hoge”; p.age = 5; : } 14 実験結果 • コンパイル時間 ▫ 型推論や暗黙的に行われるクラス・インタフェースの定義によってオー バーヘッドがかかっていると考えられる ▫ 既存のプログラムには影響を与えない • 実行時間 ▫ 実行時間には影響なく実現できた 2500 2000 30 本システム 約+40% 本システム の利用 25 内部クラス /JastAddJ 20 1500 15 1000 内部クラス/本 システムのコン パイラ 10 500 5 0 0 コンパイル時間(ミリ秒) var型/本システ ムのコンパイラ 実行時間(ミリ秒) 15 関連研究 • Whiteoak [Gil ら ‘08] ▫ Javaにおいて structural typeな型を宣言できる インスタンスは生成できない ▫ 型を明示的に定義する必要はある • Scala他 ▫ 型推論を行う言語 明示的に型を宣言する必要のない静的型付け言語 ▫ タプルを用いると、クラス定義せずに構造体を生成で きるが制限がある 16 まとめと今後の課題 • まとめ ▫ 暗黙的に型が定義・付けられる構造体を実現 動的型付け言語の記述法を静的型付け言語である Javaで実現 ▫ 暗黙的に付けられた型を取得する typeof を提供 • 今後の課題 ▫ var型の仮引数のメソッド内での利用の強化 ▫ 形式化
© Copyright 2024 ExpyDoc