コンパニオンオプジェクト - みる会図書館


検索対象: ななか+Inside PRESS 2012 夏
5件見つかりました。

1. ななか+Inside PRESS 2012 夏

3.2 クラスが簡潔に書ける class Money(var amount : BigDecima1 , def this (amount : BigDecima1) def plus (other : Money) currency Currency) { / / コンパニオンオプジェクト ( 必ず同一ファイルに定義する ) object Money { val USD = Currency. getlnstance ( "USD") val JPY = Currency. getlnstance ( " JPY") val money = new Money(100 , Money. JPY) リスト 17 第二引数にコンパニオンオプジェクトのフィールドを指定 / / コンパニオンクラス amount と DEFAULT-CURRENCY は共に private であることに注目 リスト 18 コンパニオンオプジェクトを使えばお互いの非公開メンバーにアクセスできる。 val JPY = Currency. getInstance("JPY") / / デフォルトの C 社 e れ c val USD = Currency. getInstance("USD") object Money { / / コンパニオンオプジェクト 〃以下、省略 def this (amount : BigDecima1) this (amount , Money. DEFAULT—CURRENCY) class Money(private va1 amount : BigDecima1 , val currency : Currency) { private val DEFAULT—CURRENCY def sum(monies : List [Money] ) var result : BigDecima1 for(money く一 monies){ result 十 = money . amount new Money(resu1t) JPY 〃すべてのれ e の合計を返す リスト 19 コンパニオンオプジェクト内部にファクトリメソッド (apply メソッド ) を定義する package money ななか十 inside press ◆ 18

2. ななか+Inside PRESS 2012 夏

3.2 クラスが簡潔に書ける ジェクトのコンストラクタには引数を持っことができないことです。例えば、リスト 15 は従業 員 (Employee) を読み書きできる、データベース管理システムのテープルを表すオプジェクト (EmployeeTabIe) の例です。 リスト 15 データベース管理システムのテープルを表すオプジェクトの例 〃従業員クラス class Emp10yee (val name : String) 〃従業員テープルオプジェクト 0bj ect Emp10yeeTab1e { def insert (table : Emp10yee) :Unit def se1ectA11 : List [Emp10yee] / / れ e 出 E 乙 0 eeTa e ではなく、 E 乙 0 eeT 乙 e とすると / / 常に同一のインスタンスが返される val emp10yeeTab1e = Emp10yeeTab1e emp10yeeTab1e. insert (new Emp10yee ( " Junichi Kat0" ) ) emp10yeeTabIe . se1ectAII val employees 3.2.6 コンパニオンオプジェクトで非公開メンバーに相互アクセス Money クラスの例に戻りましよう。 Money クラス用の定数フィールドを定義するにはオプジェ クトを使うわけですが、その際、コンパニオンオプジェクトという形式で定義します。コンパニオ ンオプジェクトとは、同じファイルや同じパッケージ内でクラスと同じ名前で定義されたオプジェ クトのことを指します。また、対になっているクラスをコンパニオンクラスと呼びます * 10 。コン パニオンクラスとコンパニオンオプジェクトを使うメリットは、お互いの非公開メンバー ( フィー ルドとメソッドの両方 ) にアクセスできることです。リスト 16 の例では、コンパニオンとなるク ラスとオプジェクトを同一ファイルに定義しています。 コンパニオンオプジェクトのフィールドを使えば static フィールド相当のことができます ( リス ト 17 ) 。お互いの非公開メンバーへのアクセスは、リスト 12 の例で見てみましよう。 Money オプ ジェクトの DEFAULT-CURRENCY には、 Money クラスからアクセス可能です。また、 Money クラスの amount には、 Money オプジェクトからアクセス可能です。 * 10 Java では名前空間の衝突が発生してしまいますが、 ScaIa の場合は発生しません。 / / コンパニオンクラス import java . util . Loca1e import java. util . Currency package money ファイルに定義する リスト 16 コンパニオンオプジェクトの例。 ななか十 inside press ◆ 17 コンパニオンとなるクラスとオプジェクトを同一

3. ななか+Inside PRESS 2012 夏

3.2 クラスが簡潔に書ける import java. util . Currency import java. util . Loca1e class Money(var amount : BigDecimaI , def this(amount : BigDecima1) def plus (other : Money) 〃必ず同一ファイルに定義する object Money { currency Currency) { def apply(amount : BigDecima1 , currency : Currency) new Money (amount , currency) / / 補助コンストラクタを廃止し、コンパニオンオプジェクトで複雑な生成を担うことも可能 def apply(amount : BigDecima1) new Money (amount , Currency. getlnstance (LocaIe. getDefauIt) ) 3.2.7 コンパニオンオプジェクトでファクトリを実装 コンパニオンオプジェクトにはファクトリ ( インスタンスの生成 ) としての役割もあります。リ スト 13 のように apply メソッドを定義することで、 new 演算子を利用せずにインスタンスを作 ることができるようになります。 apply メソッドは明示的に呼び出すのではなく、「コンパニオ ンオプジェクト名 ( 引数 ) 」のように記述することで apply メソッドを呼び出します。例えば、リ スト 20 では、 Money(100, Money. JPY) は Money. apply(100, Money. JPY) と、 Money(150) は Money. apply(150) と同じ意味になります。これは糖衣構文 ( シンタックスシュガー ) といって、 コードの読み書きのしやすさのために導入される構文です。 リスト 20 叩 ply メソッドの呼び出し例。糖衣構文により簡単に呼び出せる / / れ e に 0 のれ e JP りは、れ e 叩 2 に 0 の Money.JPY) が呼び出されて Money(150)) assert(result れる / / れ e に 5 のは、れ e . 叩 2 切に 5 のが呼び出され、れ e 田 Mo れ e ( プ 50 , れ e JPY) が実行さ val a = Money( 100 , Money. JPY) / / れ e 田れ e ( 10 のれ e 咽りが実行される ななか十 inside press ◆ 19

4. ななか+Inside PRESS 2012 夏

3 基礎編 : 変数とクラスを学ぶ , こで学ぶこと ・変数 (val と var の違い、型と型推論 ) ・クラス ( フィールドとメソッド、コンストラクタ ) ・オプジェクト ( コンパニオンオプジェクト ) ・プログラミングスタイルの使い分け いよいよ、 Scala の基本文法を学んでいきましよう。基礎編では主に 「変数」と「クラス」につい て学びます。 3.1 変数 : 再代入の有無がポイント 学習のためにはインタブリタで一文ずっ確認した方が理解しやすいでしよう。そこで、 は REPL を利用します。 * 2 「 v 引」で再代入できない変数を定義する 典型的な変数として、文字列型の変数を次のように定義してみます。 scala> val name "Sca1a" name: java. lang. String = Sca1a 変数を宣言するには「 val 」あるいは「 var 」を最初に配置し、その後に変数名を記述します。 の例では val で宣言し、初期値は代入演算子の後に続けて指定しています。また、変数宣言の文を 記述し Enter キーを押すと、次の行に「 name: java. lang. String = Scala 」と表示されます。これ は name という変数の中に Str ⅲ g 型で ' ' Scala ”という値を保持していることを表します。ちなみ に Scala の文字列型には Java の文字列型 (java. lang. String) が使われます。 val の変数は、 Java でいう final 変数と同じ扱いです。つまり、初期値が必要で、再代入は禁止されます試しに代入 すると次のようにラーが発生します。そういう意味では " 変数 " ではなく、 " 定数 : という表現 が適切かもしれません。 S cala> name error : reassignment tO val く CO Ⅱ sole > : 6 : name 3.1 ユ 3.1.2 再代入できる変数は「 var 」で定義する 続いて、もうーっの宣言方法である var の場合です。 こちらは再代入が可能な“普通の”変数 です。 * 2REPL ではクラスに紐付かない変数やメソッドを定義できます。 ななか十 inside press ◆ 10

5. ななか+Inside PRESS 2012 夏

6.3 ケースクラスでバリューオプジェクトを簡単実装 case List(3,3,3) = > "three" / / コレクションの場合 = > throw new IIIega1ArgumentException case print1n(convertNumberToString(I) ) / / 0 れ e print1n(convertNumberTOString("2") ) / / t 田 0 print1n(convertNumberToString(List(3,3,3)) / / three t'Katot') val personName = PersonName ( "Junichi" println(pl = (2) / / . eq 乙 s 朝 2 ) が呼ばれる "KATO" ) val p2 = PersonName ( " JUNICHI" "Kato") va1 pl = PersonName ( " Junichitt リスト 30 ケースクラスで定義したバリューオプジェクトの利用 print1n(convertNumberToString(0.5)) / / 例外発生 ・ケースクラスに対応するコンパニオンオプジェクトとファクトリメソッドを追加する このケースクラスを宣言するとコンパイラが以下を自動的に追加します。 case class PersonName(firstName: String, 1astName: String) うに記述できます。 機能を提供するクラスです。例えば、人の名前を表す人名というバリューオプジェクトは次のよ ケースクラスは、バリューオプジェクト ( 値を表現するオプジェクト ) を実装するために必要な 6.3 ケースクラスでバリューオプジェクトを簡単実装 print1n("IastName %s" . format(12)) / / LastName = Ka カ 0 val PersonName ( ー 12 ) = personName / / LastName だけを抽出 LastName = イ 0t0 / / ↑ firstName = れ c れを , print1n("firstName = %s, 1astName = . format(f , 1 ) ) val PersonName (f , 1 ) personName 〃フィールドを抽出 ScaIa には Java のインタフェースと同じ機能はありません。 6.4 トレイトは実装コードを書けるインタフェース です。 このため、たった 1 行の記述で、リスト 30 のようにバリューオプジェクトを扱うことが可能 ・ toString 、 hashCode 、 equals メソッドの実装を行う ケースクラスのコンストラクタの引数宣言を val で行う Scala ではインタフェースの代 ななか十 inside press ◆ 26 フェースのようなものです。リスト 31 は英語と日本でのあいさつを使い分けるアプリをトレイ わりにトレイト (trait) を使います。このトレイトを一言でいうと、実装コードを書けるインタ