Javaのための暗黙的に型定義される構造体

Slides:



Advertisements
Similar presentations
オブジェクト指向 言語 論 第八回 知能情報学部 新田直也. 多相性(最も単純な例) class A { void m() { System.out.println( “ this is class A ” ); } } class A1 extends A { void m() { System.out.println(
Advertisements

独習JAVA Chapter 6 6.6 クラスの修飾子 6.7 変数の修飾子 結城 隆. 6.6 クラスの修飾 abstract インスタンス化できないクラス。1つまたは複数のサブクラスで 実装してはじめてインスタンス化できる。 final 継承されたくないことを明示する。これ以上機能拡張 / 変更でき.
C 言語講座第 5 回 構造体. 構造体とは ... 異なる型の値をまとめて新しい型とする 機能がある . つまり , 複数の変数を 1 つのまとまりにできる . 配列と違って同じ型でデータをまとめるのではな く違った型のデータをまとめられる .
ソフトウェア工学 知能情報学部 新田直也. オブジェクト指向パラダイムと は  オブジェクト指向言語の発展に伴って形成され てきたソフトウェア開発上の概念.オブジェク ト指向分析,オブジェクト指向設計など,プロ グラミング以外の工程でも用いられる.  ソフトウェアを処理や関数ではなくオブジェク.
プログラミング言語論 第10回(演習) 情報工学科 木村昌臣   篠埜 功.
6.4継承とメソッド 6.5継承とコンストラクタ 11月28日 時田 陽一
アルゴリズムとデータ構造 第2回 線形リスト(復習).
プログラミング基礎I(再) 山元進.
第13回構造体.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
アルゴリズムとデータ構造1 2007年6月12日
Javaのインタフェース についての補足 2006年5月17日 海谷 治彦.
情報伝播によるオブジェクト指向プログラム理解支援の提案
プログラミング言語論 第6回 型 情報工学科 篠埜 功.
第2回:Javaの変数と型の宣言 プログラミングII 2007年10月2日.
アルゴリズムとデータ構造 2011年6月13日
構造体.
プログラミング演習II 2004年12月 21日(第8回) 理学部数学科・木村巌.
第6回独習Javaゼミ 第6章 セクション4~6 発表者 直江 宗紀.
第10回 プログラミングⅡ 第10回
補足説明.
細かい粒度でコードの再利用を可能とするメソッド内メソッドのJava言語への導入
ソフトウェア工学 知能情報学部 新田直也.
アルゴリズムとプログラミング (Algorithms and Programming)
細かい粒度で コードの再利用を可能とする メソッド内メソッドと その効率の良い実装方法の提案
オブジェクト指向 プログラミング 第八回 知能情報学部 新田直也.
独習JAVA 6.8 コンストラクタの修飾子 6.9 メソッドの修飾子 6.10 ObjectクラスとClassクラス 11月28日(金)
オブジェクト指向 プログラミング 第十一回 知能情報学部 新田直也.
オブジェクト指向 プログラミング 第十三回 知能情報学部 新田直也.
静的型付きオブジェクト指向言語 のための 暗黙的に型定義されるレコード
暗黙的に型付けされる構造体の Java言語への導入
Java8について 2014/03/07.
オブジェクト指向言語論 第十一回 知能情報学部 新田直也.
オブジェクト指向言語論 第八回 知能情報学部 新田直也.
オブジェクト指向 プログラミング 第十ニ回 知能情報学部 新田直也.
オブジェクト指向言語論 第十一回 知能情報学部 新田直也.
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
プログラミング言語論 第六回 理工学部 情報システム工学科 新田直也.
アルゴリズムとプログラミング (Algorithms and Programming)
プログラミング言語論 第十三回 理工学部 情報システム工学科 新田直也.
オブジェクト指向 プログラミング 第八回 知能情報学部 新田直也.
ソフトウェア工学 知能情報学部 新田直也.
オブジェクト指向言語論 第十二回 知能情報学部 新田直也.
プログラミング言語論 第十一回 理工学部 情報システム工学科 新田直也.
統合開発環境によって表現された 言語機構によるコードのモジュール化
C#プログラミング実習 第3回.
アルゴリズムとデータ構造 2012年6月11日
プログラムの差分記述を 容易に行うための レイヤー機構付きIDEの提案
サブゼミ第7回 実装編① オブジェクト型とキャスト.
アルゴリズムとデータ構造1 2009年6月15日
統合開発環境のための プログラミング言語拡張 フレームワーク
JAVA入門⑥ クラスとインスタンス.
オブジェクト指向言語論 第十一回 知能情報学部 新田直也.
オブジェクト指向言語論 第九回 知能情報学部 新田直也.
アルゴリズムとデータ構造 2010年6月17日
ソフトウェア工学 知能情報学部 新田直也.
フレンド関数とフレンド演算子.
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
オブジェクト指向言語論 第七回 知能情報学部 新田直也.
Javaとは Javaとはオブジェクト指向言語でJava VM(Java仮想マシン)と呼ばれるプログラム上で動作します。
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
オブジェクト指向言語における セキュリティ解析アルゴリズムの提案と実現
プログラミング演習II 2003年12月10日(第7回) 木村巌.
情報処理Ⅱ 小テスト 2005年2月1日(火).
オブジェクト指向言語論 第九回 知能情報学部 新田直也.
オブジェクト指向言語論 第十回 知能情報学部 新田直也.
C言語講座第5回 2017 構造体.
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
計算機プログラミングI 第2回 2002年10月17日(木) 履習登録 複習 ライブラリの利用 (2.6-7) 式・値・代入 (2.6-8)
計算機プログラミングI 第10回 2002年12月19日(木) メソッドの再定義と動的結合 クイズ メソッドの再定義 (オーバーライド)
Presentation transcript:

Javaのための暗黙的に型定義される構造体 大久保 貴司 千葉 滋  東京工業大学 数理・計算科学専攻 テスト 文字の大きさ

静的型付け言語における構造体の利用 構造体(レコード型) 静的型付け言語における構造体 複数の異なる型のデータを まとめるために利用  まとめるために利用 静的型付け言語における構造体 定義が別途必要 クラス等 構造体は単純なデータ構造 値の出し入れさえできれば良い メソッドや関数は必要ない Java 人を表す構造体を 利用したい class Person{ String name; int age; } ・プログラミングにおいて複数のデータをまとめたい場合がよくあります。 ・そのような場合構造体(レコード型)がよく用いられます。 ・実際にはJavaなどのようにクラスベースオブジェクト指向言語では、クラスによって代用されるため、サポートされていないこと多い。 ・このような構造体を利用する場合、一般的に、まず構造体を定義して、それを用います。 例えば、図!! しかし Person p = new Person(); p.name = “hoge”; p.age = 20;

構造体の定義は省略したい 局所的にしか利用しない場合 タプルの利用 新たな定義なしに生成可能 構造体として扱う上での制限 任意の数のメンバをもつタプルは簡潔に記述できない 各メンバへのアクセスは名前でなく index等 不可変 なので構造体のための定義は省略しても良いのではないかと我々は考えます。 特にあるメソッドの一部など局所的に そこで、構造体と似たデータ構造としてタプルがあります。 タプルは異なるデータ構造を組として表します。 しかし構造体の変わりとして用いるにはいくらか制限があります。 言語によりますが、… val p = (“hoge”, 20) // p : Tuple2[String, Int] Scalaのタプル

動的型付け言語なら可能 オブジェクトの型を定義する必要がない 動的型付け言語だからできる記述法 オブジェクトのメンバ (プロパティ) は自由に追加可能 動的型付け言語だからできる記述法 静的型付け言語 にこのまま導入することは不可能 Java JavaScript       class Person{ String name; int age; } 定義する必要なし ・一方、動的型付け言語では、そのような定義をわざわざする必要はありません。 ・なぜなら、型を明示的に宣言する必要がないからです。 ・例えば、JavaScriptでは、……プロパティを任意に追加できます。 ・従って、先ほどのプログラムは、クラス定義だけを省いたような記述で書くことができます。 ・しかし、これは動的型付け言語であるからできる記述法であり、静的型付けを維持したままJavaにこのような記述法を導入するのは難しい。 Person p = new Person(); p.name = “hoge”; p.age = 20; var p = {}; p.name = ”hoge”; p.age = 20;

提案: 暗黙的に型定義される構造体 動的型付け言語のような構文で構造体を利用可能 フィールド以外で利用可能 Javaで実現 ストラクトオブジェクトと var 型を導入 メンバを自由に追加可能 追加したメンバにはアクセス可能 フィールド以外で利用可能 そこで、本研究ではJavaにおける暗黙的に型定義される構造体を提案します。 本システムではストラクトオブジェクトとvar型を導入し、型を暗黙的に付けることで、先ほどのJavaScriptのコードのように、 クラス定義をせずに構造体を生成・利用が可能となっています。 これが本システムを用いたJavaで書いた構造体を利用するプログラムです。 ストラクトオブジェクトとはnew()で生成される構造体を表すオブジェクトであり、 Var型とはストラクトオブジェクトを参照する変数の宣言時の型です。 このvar型で宣言された変数pを用いて、自由にストラクトオブジェクトにメンバを追加でき、 追加したメンバの値は取り出すことができます。 Var型とはストラクトオブジェクトを参照する変数の宣言時の型であり、コンパイル時に暗黙的に型付けされます。 なので、JavaScriptのvar変数というよりは、C#のvar型に近く、それを構造体に適用したものです。 本システムを用いた Java var 型: ストラクトオブジェクトを参照する変数の宣言時の型 ストラクトオブジェクト( 構造体を表すオブジェクト)を生成 var p = new(); p.name = “hoge”; p.age = 20; int i = p.age;

暗黙的な型定義 structural type [Cardelli ‘88]+ 型推論 型はstructural type を用いて表現 型は内部のデータ構造によって区別される 型 = アクセス可能なメンバの集合 変数の型推論 構造体のメンバへの代入から適切な型を決定 変数が定義されているメソッド内をパース 本システムにおける構造体の型は、structural typeを用いて表現しています。 Structural typingとはその内部のデータ構造によって型が決定される型システムです。 本システムでは、型はアクセス可能なメンバの集合として表されます。 そして、アクセス可能なメンバというのはメンバの代入式から決定しています。 例えば、この例では 具体的には、まずストラクトオブジェクトの型が…のようにして決定されます。 変数 p の型 var p = new(); p.name = “hoge”; p.age = 20; int i = p.age; Struct{ String name; int age; } p.name = “hoge”; p.age = 10;

構造体のフィールドの型 構造体のフィールドへ異なる型のオブジェクトが代 入されている場合 フィールドの型 = 代入される各オブジェクトの型のアッ パーバウンドの型 class Shape{…} class Circle extends Shape{…} class Square extends Shape{…} var a = new(); a.obj = new Circle(); a. obj = new Square(); 先ほど説明した通り、構造体の型を決めるとき、メンバの代入式から、メンバの型を決定します。 あるメンバへの代入が1つだけなら、その代入しているオブジェクトの型をメンバの型と用いればよいのですが、 この場合、これらの代入している各オブジェクトのアッパーバウンドな型、 つまり、共通のスーパータイプの中で最もサブタイプである型がメンバの型となります。 この例では、 なぜなら、a.objはCircleもSquareも代入可能な変数です。従って、objの型はこれらのスーパータイプでなければなりません。 Object型とすれば、その中で 変数 a の型 Struct{ Shape obj; }

Subtyping new()によって初期化されていないvar 型の変数へ 既存のストラクトオブジェクトを代入  既存のストラクトオブジェクトを代入 必要に応じてスーパータイプを生成 共通のアクセス可能メンバのみメンバとして持つ var circle = new(); circle.color = “red”; circle.radius = 3; var square = new(); square.color = “blue”; square.size = 5; var shape; shape = circle; shape = square; struct{ String color; int radius; } circleの型 new()で 初期化 new()で 初期化 squareの型 struct { String color; int size; } 一方、var型の変数に他の変数が参照するストラクトオブジェクトを代入することも可能です。 図説明。 このような場合、 その変数の型はそれらの中で共通なアクセス可能なメンバになります。 具体的には、 このようにすることで、クラスの継承関係のような振る舞いが可能となる。 つまり、shapeの型がcircleとsquareの型のスーパータイプとして振る舞っている。 代入 shapeの型 Struct{ String color; }

メソッドへの受け渡し(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

メソッドへの受け渡し(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; } これを用いると、Javaなどでよく見られる、メソッドの返り値として、 複数のオブジェクトを返したい時に、わざわざそれ用のクラスを定義しなければいけないという問題を解決する事が可能となります。

p と同じ型のストラクトオブジェクトのみ格納可能 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); } 本システムでは、暗黙的に型を付けることで、記述を簡単にしているが、そのため構造体の型を明示的に型の名前を指定できない。 変数宣言はvarを用いて行われ、ストラクトオブジェクトの生成はnewで行われるため必要ないようにも思えるが、 ジェネリクスの型引数やinstanceofによる比較など、明示的に型の名前が必要になる場合が他にも色々あります。 そのため、構造体の型を取得するために、本システムではtypeof演算子を提供しています。 ー>図で説明 p の型 Struct{ String name; int age; }

実装 標準のバイトコードに変換 var 型 = Object 型 ストラクトオブジェクト 変数ごとにインタフェースを作成、必要に応じてキャスト インタフェースがアクセス可能なフィールドを表す ストラクトオブジェクト 上記のインタフェースを実装するクラスのインスタンス ストラクトオブジェクトを表すクラス class Var$$0 implements StringName{   String name;   String getName(){return name;}   void setName(String name){    this.name = name;} } 変数の型 本システムでは、 interface StringName{   String getName();   void setName(String name) }

実験 内部クラスによる構造体と本システムを比較 構造体を生成・操作するメソッドを100個定義し、実行 するプログラム コンパイル時間と実行時間を計測 内部クラスを用いた構造体 本システムを用いた構造体 run(){  class Person{…}  Person p = new Person();  p.name = “hoge”;  p.age = 5;       : } run(){  var p = new();  p.name = “hoge”;  p.age = 5;        : }

実験結果 コンパイル時間 実行時間 型推論や暗黙的に行われるクラス・インタフェースの定義によってオー バーヘッドがかかっていると考えられる 既存のプログラムには影響を与えない 実行時間 実行時間には影響なく実現できた 本システム の利用 本システム約+40%

関連研究 Whiteoak [Gil ら ‘08] Scala他 Javaにおいて structural typeな型を宣言できる インスタンスは生成できない 型を明示的に定義する必要はある Scala他 型推論を行う言語 明示的に型を宣言する必要のない静的型付け言語 タプルを用いると、クラス定義せずに構造体を生成で きるが制限がある

まとめと今後の課題 まとめ 今後の課題 暗黙的に型が定義・付けられる構造体を実現 暗黙的に付けられた型を取得する typeof を提供 動的型付け言語の記述法を静的型付け言語である   Javaで実現 暗黙的に付けられた型を取得する typeof を提供 今後の課題 var型の仮引数のメソッド内での利用の強化 形式化

実装 JastAddを用いてJastAddJ を拡張して実装 JastAddJ: JastAddを用いて 実装されたJavaコンパイラ Object p = new Ver$$0(); ((IntAge_StringName)p).setName(“hoge”); ((IntAge_StringName)p).setAge(20); int i = (IntAge_StringName)p).getAge(); class Ver$$0 implements IntAge_StringName{   int age; String name;   String getName(){…}   void setName(String name){…} } JastAddを用いてJastAddJ  を拡張して実装 JastAddJ: JastAddを用いて  実装されたJavaコンパイラ var p = new(); p.name = “hoge”; p.age = 20; int i = p.age;

提案: 暗黙的に型付けされる構造体 型の定義を必要としない Java における構造体 局所的にのみ利用可能 ストラクトオブジェクト 構造体を表すオブジェクト new()で生成される var 型 ストラクトオブジェクトを参照する  変数の宣言時の型 コンパイル時に型が決定される 動的型付け言語のような構文で構造体を生成・利用可能 局所的にのみ利用可能 プログラム全体で用いる場合はクラス定義 本システムを用いた構造体 var p = new(); p.name = “hoge”; p.age = 20; int i = p.age; そこで、本研究ではJavaにおける暗黙的に型付けされる構造体を提案します。 本システムではストラクトオブジェクトとvar型を導入して、型を暗黙的に付けることで、先ほどのJavaScriptのコードのように、 クラス定義をせずに構造体を生成・利用が可能となっています。 ストラクトオブジェクトとは構造体を表すオブジェクトであり、 Var型とはストラクトオブジェクトを参照する変数の宣言時の型であり、コンパイル時に暗黙的に型付けされます。 なので、JavaScriptのvar変数というよりは、C#のvar型に近く、それを構造体に適用したものです。

構造体を表す型 structural type を用いて表現 ストラクトオブジェクトの型 var 型の変数の型 型 = アクセス可能なメンバの集合 ストラクトオブジェクトの型 代入された変数のメンバ代入式から決定 var 型の変数の型 変数に代入されたストラクトオブジェクトの型から決定 P の型 暗黙的に付けられる構造体の型は、structural typeを用いて表現しています。 Structural typeはフィールドとメソッドの集合で型を表現するものですが、 本システムではアクセス可能なメンバ、つまりフィールドの集合としてあらわしている。 そして、どのようにアクセス可能なメンバというのはメンバの代入式から決定しています。 具体的には、まずストラクトオブジェクトの型が…のようにして決定されます。 var p = new(); p.name = “hoge”; p.age = 20; int i = p.age; String name; int age; ストラクト オブジェクトの型 p.name = “hoge”; p.age = 10; String name; int age;

構造体(レコード型) 構造体 Javaでは直接的にはサポートされていない 複数の異なるデータ(型)をまとめるために利用 それぞれ構造体に対応するクラスを定義 Cの構造体 struct person{ char name[10]; int age; };