scalaの予約語

この記事はscala advent calendarのDay2です(`・ω・´)

scalaの言語仕様書の4ページあたりに記載されてる、予約語についてひと通りまとめてみます。ちょっと時間なくて説明適当なところとかあるのはあとで直します、すいません(´Д`)
ちょっとだけ追記した



仕様書↓


abstract

抽象クラス表すのに使用。
ちなみに、メソッドやフィールドがabstractでも、scalaの場合は、abstractはつけません(つけると以下のようにエラーになる)

scala> abstract class A{
     |   abstract def hoge
     | }
<console>:6: error: `abstract' modifier can be used only for classes;
it should be omitted for abstract members
         abstract def hoge

case

たぶん使うとこ4種類ある。前のこのエントリ参照w

と思ったら、例外のcatchの後にもでてくるじゃん!ってことで5種類ですかね?

catch

例外受け取る。ただし、catchの部分の書き方がjavaと異なる。以下同じ処理のjavascalaで書いた

java

try{
  // 何らかの例外が投げられる可能性のある処理
}catch(IOException e){
  println("IOException発生したお")
}catch(Exception e){
  println("Exception発生したお")
}

scala

try{
  // 何らかの例外が投げられる可能性のある処理
}catch{
  case _ : IOException => println("IOException発生したお")
  case _ : Exception   => println("Exception発生したお")
}


class

classの定義。まぁjavaと同じ

def

関数の定義。ローカル関数*1の定義にも

do

do whileのdo。javaと同じ

else

if else で使う。if 〜 else 〜 の全体そのものが式で、値返すところがjavaと異なる

extends

クラスを継承するとき。Javaでは、型パラメータの境界を示す場合にも使用するが、scalaでは <: を使用する

false

Boolean型のリテラルJavaのfalseと全く同じ

final

classが継承できないことをあらわす。Javaでは変数にfinalを付けると再代入不可能な変数を意味するが、scalaの場合はvalを使用する

java scala
再代入可能な変数(mutable) int a = 1 var a = 1
再代入不可能な変数(immutable) final int a = 1 val a = 1

あと、メソッドがoverrideできないこと示す。これもjavaと同じ

finally

javaと同じ。ちなみに、finallyの中のは値かえさない。

for

javaと同じでループの処理・・・ではない!*2
foreach、map、filter、(2.8以降はwithFilterも) の(組合せの)シンタックスシュガー。

forSome

えーと、普通は省略できるから殆ど使わないんだっけかなぁ・・・。型書くところで使うんだけど。
すいません、あとで調べます(´Д`)まぁ初心者のうちは知らなくても困りません。

if

if
それ以外にも、match式のcaseの部分や、for式の、パターンガードでもつかう

implicit

大きく分けて2種類*3。暗黙変換(implicit conversion)と暗黙引数(implicit parameter)。
追記
2.8から無名関数のリテラルを書く際の引数の場所に書く文法があるらしい*4

import

基本はjavaと同じ機能。がそのほかにも色々機能追加されてる。

  • 一行で複数のclassインポートできる便利な書き方
  • 別名(alias)つける
  • fileの先頭以外でもimportできる
  • package名をimportできる
  • ある特定のものを除いて、それ以外importとか

lazy

変数の遅延評価。初めてアクセスしたときに評価される。2回目以降は、1度目に評価した値を返す。

*5

match

javaのswitchをものすごく汎用的にした感じ。詳しく書ききれないので、機能の詳細はとりあえず省略w

new

javaと同じ。インスタンス生成

null

Nullクラスの唯一のリテラルjavaのnullと同じ

object

シングルトンを定義する。先頭が小文字というのに注意。scalaの場合でも、先頭大文字で単にObjectと書けば、java.lang.Objectを表すことになる。

override

overrideした場合に、必ずつけないといけない。C#のoverrideキーワードに似てる。
ちなみに、scalaではvalやvarもoverrideできる。*6

package

packageの定義。Javaと同じようにも使えるが、異なる構文もある。たとえばListの先頭は以下のようになってます

package scala.collection
package immutable

これは以下のように1行で書いたものと意味が異なります!

package scala.collection.immutable

あとこんなふうに中括弧つかって同一ファイル内に複数のpackage書けたり

package a{
  //ここの名前空間は a

  package b{
    //ここの名前空間は a.b
  }
}

それとpackage objectの定義にも使いますね

private

普通に書くとjavaと同じように使えるが、異なる構文もある。
普通に書くとclass内でのみアクセス可能だが、以下のように

private[this]

と書くと、そのインスタンス内でのみアクセス可になる。ほかにも上記のthisの部分にpackage名入れたりとかして、javaより柔軟にアクセス制御できる

protected

普通に書くとjavaと同じように使えるが、privateの場合と同じく、そのあとに、公開する範囲を指定できる

return

関数から戻り値返す。scalaの場合省略できるので、普通書かない。また、returnを書くと、関数の戻り値の型を明示しないといけないという決まりがある。

sealed

classにつける。それをつけたものは、同一ファイル内のclassからしか継承できなくなる。

Listがsealedクラスで、:: と、 Nil同じファイルに定義されていたりとか有名(?)ですよね

super

superクラスのメソッド呼ぶときとか・・・。他になにかあったっけ?記憶が曖昧(´・ω・`)
javaと違って、型引数の境界あらわすのには使いません!

this

プライマリ以外のコンストラクタ。javaと異なる*7
ちなみに、scalaのコンストラクタは、javaと違って色々制限が厳しくなってるので、慣れないと最初結構戸惑うとおもいます。
scalaでは、プライマリコンストラクタ以外のコンストラクタは、super classのコンストラクタを呼べなかったりとか。

あとは、classのインスタンスメソッド内のコンテキストで、そのインスタンス自身を示す場合に使用。(これはjavaと同じ)

throw

例外なげる。javaと同じ

trait

一言で言うとRubyのModule。実装を持ったinterfaceって言えばいいんでしょうか?
ここもちょっと説明しきれないので、とりあえずこんな感じで。

try

javaと同じ。けど、try 〜 catch 自体が式であり、値を返す

true

Boolean型のリテラルjavaのtrueと同じ

type

javaにはないキーワード。型自体の別名(alias)を定義したり。また、抽象型というものを定義したり。
*8

val

再代入不可能(immutable)な変数を定義する

var

再代入可能(mutable)な変数を定義する

while

javaとまったく同じ

with

traitをMixinするとき。classやobject定義の場所以外でも使える

yield

for式が値を返す場合に使う

@

アノテーションをつけるとき。
ちなみにjavaの場合、アノテーションの定義にも@を使う*9が、scalaの場合は単に、StaticAnnotationクラスを継承したクラスを定義する

そして、match式での変数束縛パターンというあまり知られていないマニアックな機能もある

#

え〜〜〜となんだっけw あとで書きます m(__)m
追記しますた(・ω・)

classの内部classの型名を書く場所で使う。以下REPLで試したものをそのまま貼りつけ(コメントは追加したけど)
#の使い方と、classの内部クラスと、objectの内部classの違いの説明*10

scala> class A{ //Aというclassと、その中に、Bという内部class定義
  class B{

  }
}
defined class A

scala> val a = new A() //Aのインスタンス作成
a: A = A@52744

scala> val b:A#B = new a.B() // Aのインスタンスをつかって、Aの内部classであるBのインスタンス作成
b: A#B = A$B@1557a77

scala> val c:A.B = new a.B() // この書き方は間違い
<console>:7: error: not found: value A
       val c:A.B = new a.B()
             ^

scala> object A{ //Aのobjectと、その内部class定義
     |   class C{
     |   }
     | }
defined module A

scala> val c:A.C = new A.C() // objectの内部クラスの場合はこういう書き方
c: A.C = A$C@1d869b2

scala> val c:A#C = new A.C() // 逆に、#をつけて書くとエラー
<console>:7: error: type C is not a member of A
       val c:A#C = new A.C()

scala> new A.B() // Aのインスタンスが存在しないとBのインスタンスは作成できない
<console>:7: error: type B is not a member of object A
       new A.B()
             ^

scala> new A#B() // 上記と同じく、こういう書き方してもインスタンスは作成できない
<console>:7: error: A is not a legal prefix for a constructor
       new A#B()

他に#出てくる場所ってあったっけ?(´・ω・`)

:<

上限境界

%>

可視境界。

:>

下限境界。

<-

for式でつかう

=>

関数リテラル定義するときに、
引数 => 関数本体の式
という形で使用

=

変数に代入するとき。関数定義するとき。
*11

:

変数名:型名
関数の引数:型名
def ( 引数のりすと ):関数自体の型名
とか*12

_

関数リテラルのプレースフォルダー
パターンマッチの際に、使用しない(抽出してもその後使わない)変数を明示するとき

*1:関数の中の関数

*2:for(i <- 1 to 10) っていう感じで見た目はループっぽく使えるけど、実は関数の呼び出し

*3:変換を分けると3種類になる気もするが。単に変換する場合と、暗黙的に変換した後、さらにその変換後のclassのメソッドを呼び出す場合があるから

*4: けど自分も全然意味とか使い方分かってない。だれか教えて(´・ω・`)

*5:たとえば、GAEとかってスピンアップの時間が重要だから、classのフィールドなんかでうまく使えば便利かもね。と思いついてみたり

*6:valやvar自体、普通に定義した場合、自動でアクセサメソッドができるから

*7:javaの場合コンスタントラクタ書くときは、class名を書く

*8:そういえばthis.typeとかって使い方もあるなぁ・・・

*9: @interface っていう感じで

*10:概念自体は、Javaの場合のstaticな内部classと、staticでない内部classと同じですね

*11:どうでもいいけど、これが予約語なら、カッコとかも予約語じゃないの?予約語の定義ってなに?

*12: 何だこの説明orz