Scala 型パラメータ&関数
ドワンゴ社 新卒エンジニア向けのScala研修資料をやっていくもの
資料
型パラメータ
- Javaでいうジェネリクスの様なイメージ
- メソッドの返り値を複数取りたい場合は複数型パラメータを取るクラスを作成し、返り値のクラスをその値にしてしまうと二つ取得する事が可能
- Tuple1からTuple22まであらかじめ用意されている
以下の様に新たに作成せずとも
new Tuple2(m / n, m % n)
この様に作成する事ができる
(m / n, m % n)
共変
共変というのは、型パラメータを持ったクラスG、型パラメータAとBがあったとき、A が B を継承しているときにのみ
val : G[B] = G[A]
の様な代入が許される性質を表す- 継承先を継承元へ代入する事が可能になる
- Scalaだと定義時に
Class G [+A]
の様に先頭に+
を付与することで共変として定義する事が可能
Object[] objects = new String[1]; objects[0] = 100;
val arr: Array[Any] = new Array[String](1) <console>:7: error: type mismatch; found : Array[String] required: Array[Any]
(なんか前Effective Javaで読んだ様な...)
反変
- 共変の逆で、継承元を継承先へ代入する事が可能になる性質
- Scalaだと定義時に
Class G [-A]
の様に先頭に-
を付与することで反変として定義する事が可能
- Scalaだと定義時に
型パラメータの境界(bounds)
- 大枠はJavaのそれと同じであると理解した
関数
Scalaの関数は単に Function0 〜 Function22 までのトレイトの無名サブクラスのインスタンスなのです。
- なのでこんな感じで定義する事が可能
val add = new Function2[Int, Int, Int]{ def apply(x: Int, y: Int): Int = x + y }
ちな無名サブクラス
が実際は以下の様にシンタックスシュガーを用いて記載可能である
val add = (x: Int, y: Int) => x + y
関数本体には何の名前も付いていないことに注意してください。この、addの右辺のような定義をScalaでは無名関数と呼びます。
このような、関数を自由に変数や引数に代入したり返り値として返すことができる性質を指して、Scalaでは関数が第一級の値(First Class Object)であるといいます
関数のカリー化
以下の記事が分かり易かったため省略する
サルでもわかるカリー化とそのメリット - These Walls
メソッドと関数の違い
- メソッドは
def
から始まるもので、First Class Object
ではない
高階関数
関数を引数に取ったり関数を返すメソッドや関数のことを高階関数と呼びます。
Scala クラス & オブジェクト & トレイト
クラス
class Point(val x: Int, val y: Int)
メソッド定義
返り値の型は読みやすさのために明記すべき
private
- そのクラス内だけから
protected
- 派生クラスからのみ
private[this]
- 同じオブジェクトからのみ
private[パッケージ名]
- 同じパッケージから
protected[パッケージ名]
- 派生クラスに加えて同じパッケージに所属しているもの全て
何もつけない
- publicとなる
複数の引数リストを持つメソッド
add(x: Int)(y: Int)
の様に記載する事が可能で、シンタックスシュガー書いたりimplicit parameter
なるものや型推論の補助に使われる- 単に複数の引数を持つメソッドとしても定義可能
フィールド定義
- アクセス修飾子の意味はメソッドと同様
private[this]
をつけたフィールドへのアクセスは若干高速になる
抽象メンバー
- メソッドやフィールドにおいて中身を持たせずに定義することができる
- メソッドやフィールドの中身が無い以外は通常の定義方法と同じ
継承
- Javaと同様にextendsで継承可能
オブジェクト
オブジェクトについて
- Scalaでは全ての値がオブジェクトで、全てのメソッドは何らかのオブジェクトに属している
- そのためJavaの様にstaticフィールドやstaticメソッドを作成する事が出来ない
- 代わりに
object
キーワードによってシングルトンオブジェクトを作成し、ユーティリティメソッドやファクトリメソッドとして使用する
コンパニオンオブジェクト
クラスと同じファイル内、同じ名前で定義されたシングルトンオブジェクトは、コンパニオンオブジェクトと呼ばれます。コンパニオンオブジェクトは対応するクラスに対して特権的なアクセス権を持っています。
private[this](そのオブジェクト内からのみアクセス可能)なクラスのメンバーに対してはアクセス不可
トレイト
Scala 記法 & 制御構文
ドワンゴ社 新卒エンジニア向けのScala研修資料をやっていくもの
資料
記法
- 文字列を直接記述すると文字列自体の意味となる
- ifと記載すればifという意味になる
- 文字列をクウォートで囲んでも同様の意味となるが、通常の文字列とは別の意味を持たせるために用いる
- 'if'と記載すれば上記と同じifという意味を持つ
(
で囲んで文字列をグルーピングする('if' '(' ')')
はif()
を意味する- <条件式>のように
<>
で条件式を囲む - 要素の後の
+
はその要素が1回以上現れる事を意味する ?
は要素が0回または1回現れる事を意味する- 何らかの二つの要素の間の
|
は二つの要素どちらでも良い事を意味する
制御構文
- 構文
class
・val
・if
などのプログラムを構成するためのルール
- 式
1 + 1
、1
など評価して値になるもの
文
val i = 1
の様に定義全体として値を持たないもの
Scalaは文より式になることが多い
ブロック式
{}
で複数の式の並びを囲むとそれ全体が式となる
if式
while式
- Javaのwhile式と同じ
return式
- 早期
return
の様に使用してメソッドを抜けて記述を簡略化できる - メソッドを脱出する必要が無ければreturn文は必要ない
for文
yield
で値を加工出来る点以外は特段変わった点はなし
match式
- Javaでいうswitch文みたいなものだが、値の取り出しや型でのパターンマッチが可能
Scalaの基本
ドワンゴ社 新卒エンジニア向けのScala研修資料をやっていくもの
資料
hello-world
- そういうものかという感じ
簡単な計算
- そういうものかという感じ
変数の基本
ほとんどの場面においてvarは使わずにvalを使う
- val = 値の再代入不可
- var = 値の再代入可能 ※ 型の違いは判定してくれる
基本的には型推論も働くが、このように型を明示することも可能
val x: Int = 3 * 3
sbtでプログラムをコンパイル・実行する
- とりあえず書いてある通りに実行し成功
- runコマンドはコンパイルしてmainメソッドを実行してくれるそう
ちなsbtコンソールはexitで抜けれた
IDE
用意されていたサンプルプロジェクトをgit cloneし、IntellijでHello Word
するまでは完了
JavaのSerializableについて
仕事で見かけてイマイチ理解してなかったため調べてみる。
シリアライズやデシリアライズについて
シリアライズ化可能=ファイルに書き出したりファイルから読み込んだり出来ることと理解した
【Java】Serializableの基本(シリアライズ・直列化) - TASK NOTES
Serializableとは
オブジェクトをシリアライズ可能にするにはjava.io.Serializableインタフェースを実装する必要があります。
SerializableはC言語を触った事がある人なら理解しやすいと思いますが、「バイト配列に変換できますよ」 って マーカー です。
つまり
- Javaでクラスをファイルに読み書き可能にするには
Serializable
を継承させる必要がある Serializable
自体に実装は空で目印のようなもの
Java ボクシング について
EffectiveJavaを読んでいて、ボクシングという単語が出てきてた時に、一瞬井上尚弥が頭を過ぎった自らを戒めるべくJavaのボクシングについて改めて整理する
プリミティブ型と参照型について
Javaにはプリミティブ型と参照型が存在する
プリミティブ型はそれ自身が値であり何のメソッドも持たない
プリミティブ型と参照型の小話
少し本題と話が逸れるが、プリミティブ型と参照型についてなるほどと思った事をまとめておく
初期値の違いについて
- 参照型:nullが使用可能
- プリミティブ型:例えば整数の場合初期値が0
初期値を明示的にnullにしておきたい場合、参照型が適している
ValueOfについて
新たな値を生成する際には、new Integer(10)
よりInteger.ValueOf(10)
の方が新たなオブジェクトが生成されずメモリ的に効率が良い
ちなみにIntegerの場合、-128~127の範囲の値には事前に生成されたオブジェクトが利用され、その範囲外の場合異なるオブジェクトになる
プリミティブ型のラッパークラス
とはいえ値の操作が出来ないと不便である。
そこで、プリミティブ型の値を操作するメソッドを持ったラッパークラスが存在する。
当初は明示的に変換が必要だったが、Java5.0からプリミティブ型と参照型の自動変換が可能となった。 この自動変換をそれぞれ
- プリミティブ→ラッパーへの自動変換はオートボクシング
- ラッパー→プリミティブへの自動変換はアンボクシング
と呼ぶ
参考
Java本格入門 ~モダンスタイルによる基礎からオブジェクト指向・実用ライブラリまで 谷本 心 https://www.amazon.co.jp/dp/477418909X/ref=cm_sw_r_tw_dp_41KT0MVGQ0MYMYBMYFXV?_encoding=UTF8&psc=1 @amazonJPより