gotoshin

主に学んだ事の自分メモ用です。記事に書くまでも無いような事はhttps://scrapbox.io/study-diary/に書いてます。

Scala 型パラメータ&関数

ドワンゴ社 新卒エンジニア向けのScala研修資料をやっていくもの

資料

Introduction · 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]の様に先頭に+を付与することで共変として定義する事が可能
  • Javaだと以下の様なコードがコンパイルが通ってしまう

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]の様に先頭に-を付与することで反変として定義する事が可能

型パラメータの境界(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 クラス & オブジェクト & トレイト

クラス

  • プライマリコンストラク

    • 構文上記述する事は可能だが、1クラスにつき1つのコンストラクタしか扱わない
  • 以下の様にコンストラクタの引数と同名のフィールドを定義し、その変数を外部に公開する事が可能

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](そのオブジェクト内からのみアクセス可能)なクラスのメンバーに対してはアクセス不可

トレイト

  • フィールドが持てるJavaのinterfaceの様なものと一旦は理解した
    • 複数のトレイトを1つのクラスやトレイトにミックスインできる
    • 直接インスタンス化できない
    • クラスパラメータ(コンストラクタの引数)を取ることができない

Scala 記法 & 制御構文

ドワンゴ社 新卒エンジニア向けのScala研修資料をやっていくもの

資料

Introduction · Scala研修テキスト

記法

  • 文字列を直接記述すると文字列自体の意味となる
    • ifと記載すればifという意味になる
  • 文字列をクウォートで囲んでも同様の意味となるが、通常の文字列とは別の意味を持たせるために用いる
    • 'if'と記載すれば上記と同じifという意味を持つ
  • (で囲んで文字列をグルーピングする
  • ('if' '(' ')')if()を意味する
  • <条件式>のように<>で条件式を囲む
  • 要素の後の+はその要素が1回以上現れる事を意味する
  • ?は要素が0回または1回現れる事を意味する
  • 何らかの二つの要素の間の|は二つの要素どちらでも良い事を意味する

制御構文

  • 構文
    • classvalifなどのプログラムを構成するためのルール
    • 1 + 11 など評価して値になるもの
    • val i = 1の様に定義全体として値を持たないもの
  • Scalaは文より式になることが多い

ブロック式

  • {}で複数の式の並びを囲むとそれ全体が式となる

if式

  • Javaのif式と同じ使い方をする
  • Scalaの制御構文は全て式であり、つまり何らかの値を返す

while式

  • Javaのwhile式と同じ

return式

  • 早期returnの様に使用してメソッドを抜けて記述を簡略化できる
  • メソッドを脱出する必要が無ければreturn文は必要ない

for文

  • yieldで値を加工出来る点以外は特段変わった点はなし

match式

  • Javaでいうswitch文みたいなものだが、値の取り出しや型でのパターンマッチが可能

Scalaの基本

ドワンゴ社 新卒エンジニア向けのScala研修資料をやっていくもの

資料

Introduction · Scala研修テキスト

hello-world

  • そういうものかという感じ

簡単な計算

  • そういうものかという感じ

変数の基本

  • ほとんどの場面においてvarは使わずにvalを使う

    • val = 値の再代入不可
    • var = 値の再代入可能 ※ 型の違いは判定してくれる
  • 基本的には型推論も働くが、このように型を明示することも可能val x: Int = 3 * 3

sbtでプログラムをコンパイル・実行する

  • とりあえず書いてある通りに実行し成功
  • runコマンドはコンパイルしてmainメソッドを実行してくれるそう

ちなsbtコンソールはexitで抜けれた

IDE

用意されていたサンプルプロジェクトをgit cloneし、IntellijHello Wordするまでは完了

M1 Mac にJDKとstbを入れる

Scalaの環境構築 - Qiita

大まかな手順

  1. JDKのインストール
  2. stbのインストール

JDK インストール

stbのインストール

brew install sbt
sbt console

と入力してscala>が表示されたのでOK!

JavaのSerializableについて

仕事で見かけてイマイチ理解してなかったため調べてみる。

シリアライズやデシリアライズについて

シリアライズ化可能=ファイルに書き出したりファイルから読み込んだり出来ることと理解した

【Java】Serializableの基本(シリアライズ・直列化) - TASK NOTES

Serializableとは

  • オブジェクトをシリアライズ可能にするにはjava.io.Serializableインタフェースを実装する必要があります。

  • SerializableはC言語を触った事がある人なら理解しやすいと思いますが、「バイト配列に変換できますよ」 って マーカー です。

Serializable について - Qiita

つまり

  • 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より