Scala導入ティップス

ABSTRACT CLASSES

Traitではパラメータを定義できないため、パラメータを定義できるTraitとして利用。
Javaコードから呼び出す際にも使用。
拡張クラスは、abstract classを一つだけしか利用できない。

以下Traitでは変数を定義できない。

trait Animal(name: String) --->コンパイルエラー

abstract class により変数を定義。

abstract class Animal(name: String)

Ex) Pet(name)abstract class であることを示す。

abstract class Pet (name: String) {
    def speak: Unit = println(s"My name is $name")
}

class Dog(name: String) extends Pet(name)

val d = new Dog("Fido")
d.speak

クラスメンバーにabstract typeを含む場合(具体的な値やメソッドが定義されていない)にもabstract classを使用。

// Scala program to illustrate how to 
// create an abstract class 

// Abstract class 
abstract class myauthor 
{ 
	
	// abstract method 
	def details() 
} 

// GFG class extends abstract class 
class GFG extends myauthor 
{ 
	def details() 
	{ 
		println("Author name: Ankita Saini") 
		println("Topic name: Abstract class in Scala") 
	} 
} 

object Main 
{ 
	// Main method 
	def main(args: Array[String]) 
	{ 
		// objects of GFG class 
		var obj = new GFG() 
		obj.details() 
	} 
} 

ABSTRACT TYPE MEMBERS

具体的な型のタイプ、値、メソッドなどを定義していないクラスメンバー

https://docs.scala-lang.org/tour/abstract-type-members.html

// Scala program of abstract type member 

// Declaring an abstract class 
abstract class vehicle (name:String) 
{	 
	// This is an abstract member 
	// with undefined implementation 
	val category: String	 
	
	// A function that is used to print 
	// the value of the abstract member 
	def car_type{ println(category) } 
	override def toString = s" The vehicle type is $category"
} 

// Now extend the classes bike, car, 
// truck and bus and provide values 
// for the variable type 

class car (name:String) extends vehicle (name) 
{ 
	// assigning the value of 
	// the abstract member as car 
	val category = "car"			
} 
class bike (name:String) extends vehicle (name) 
{ 
	// assigning the value of 
	// the abstract member as bike 
	val category = "bike"		
} 
class bus (name:String) extends vehicle (name) 
{ 
	// assigning the value of 
	// the abstract member as bus 
	val category = "bus"			
} 
class truck (name:String) extends vehicle (name) 
{ 
	// assigning the value of 
	// the abstract member as truck 
	val category = "truck"		
} 

object AbstractFieldsDemo extends App 
{ 
	// assigning the name as Honda in the abstract 
	// class where the category value is car 
	val car = new car("Honda") 
	
	// assigning the name as Yamaha in the abstract 
	// class where the category value is bike 
	val bike = new bike("Yamaha") 
	
	// assigning the name as Tata in the abstract 
	// class where the category value is bus 
	val bus = new bus("Tata")	 
	
	// assigning the name as Ashok_Leyland in the 
	// abstract class where the category value is truck 
	val truck = new truck("Ashok_Leyland") 
	
	// implementing the function 
	// car_type for the object car 
	car.car_type 
	
	// implementing the function 
	// car_type for the object bus 
	bus.car_type 
	
	// implementing the function 
	// car_type for the object truck 
	truck.car_type	 
	
	// implementing the function 
	// car_type for the object bus 
	bike.car_type	 
	println(car) 
	println(bus) 
	println(truck) 
	println(bike) 
} 

Keywords/reserved symbols

https://docs.scala-lang.org/tutorials/FAQ/finding-symbols.html

// Keywords
<-  // Used on for-comprehensions, to separate pattern from generator
=>  // Used for function types, function literals and import renaming

// Reserved
( )        // Delimit expressions and parameters
[ ]        // Delimit type parameters
{ }        // Delimit blocks
.          // Method call and path separator
// /* */   // Comments
#          // Used in type notations
:          // Type ascription or context bounds
<: >:      // Upper and lower bounds
<%         // View bounds (deprecated)
" """      // Strings
'          // Indicate symbols and characters
@          // Annotations and variable binding on pattern matching
`          // Denote constant or enable arbitrary identifiers
,          // Parameter separator
;          // Statement separator
_*         // vararg expansion
_          // Many different meanings

MODIFIERS

Method modifiers should be given in the following order (when each is applicable):

Annotations, each on their own line

Override modifier (override)
Access modifier (protected, private)
Implicit modifier (implicit)
Final modifier (final)

def
@Transaction
@throws(classOf[IOException])
override protected final def foo(): Unit = {
  ...
}

Override

サブクラスによる元クラスの内容(メソッド)を上書き(変数の定義は不変)

Self Reference(this)

On the inside of a class, the name this represents the object on which the current method is executed.

Add the functions less and max to the class Rational.

  class Rational(x: Int, y: Int) {
    ...
    def less(that: Rational) =
    numer * that.denom < that.numer * denom

    def max(that: Rational) =
      if (this.less(that)) that else this
  }

Note that a simple name x, which refers to another member of the class, is an abbreviation of this.x. Thus, an equivalent way to formulate less is as follows.

  def less(that: Rational) =
    this.numer * that.denom < that.numer * this.denom

Predef

Assertions

These methods support program verification and runtime correctness.

final def assert(assertion: Boolean, message: => Any): Unit
Tests an expression, throwing an AssertionError if false.

def assert(assertion: Boolean): Unit
Tests an expression, throwing an AssertionError if false.

final def assume(assumption: Boolean, message: => Any): Unit
Tests an expression, throwing an AssertionError if false.

def assume(assumption: Boolean): Unit
Tests an expression, throwing an AssertionError if false.

final def require(requirement: Boolean, message: => Any): Unit
Tests an expression, throwing an IllegalArgumentException if false.

def require(requirement: Boolean): Unit
Tests an expression, throwing an IllegalArgumentException if false.

def, val, var

def - defines an immutable label for the right side content which is lazily evaluated - evaluate by name.

val - defines an immutable label for the right side content which is eagerly/immediately evaluated - evaluated by value.

var - defines a mutable variable, initially set to the evaluated right side content.

LazyLists " #:: "

https://docs.scala-lang.org/overviews/collections-2.13/concrete-immutable-collection-classes.html

以下のようなフィボナッチ数列の演算で、#:: とすることで結果を呼び出さない限り演算しないようにする。

scala> def fibFrom(a: Int, b: Int): LazyList[Int] = a #:: fibFrom(b, a + b)
def fibFrom(a: Int, b: Int): LazyList[Int]

パラメータ入力しても演算結果を返さない。

scala> val fibs = fibFrom(1, 1).take(7)
val fibs: scala.collection.immutable.LazyList[Int] = LazyList(<not computed>)

toListメソッドによる呼び出し

scala> fibs.toList
val res0: List[Int] = List(1, 1, 2, 3, 5, 8, 13)

POLYMORPHIC METHODS

https://docs.scala-lang.org/tour/polymorphic-methods.html#inner-main

型をパラメータとする場合 [ ] 、変数は ( ) を用います。型をパラメータと定義することでメソッドの自由度が大幅に増加します。 println 等による具体的な値を入力して呼び出しする際には [ ] は省略できます(Scalaコンパイラーによる自動認識)。

def listOfDuplicates[A](x: A, length: Int): List[A] = {
  if (length < 1)
    Nil
  else
    x :: listOfDuplicates(x, length - 1)
}
println(listOfDuplicates[Int](3, 4))  // List(3, 3, 3, 3)
println(listOfDuplicates("La", 8))  // List(La, La, La, La, La, La, La, La)

http://twitter.github.io/scala_school/type-basics.html

コンパイラオプション

https://docs.scala-lang.org/overviews/compiler-options/index.html#Standard_Settings

scala.sbt

scalaVersion := "2.13.3"

scalacOptions ++= Seq(
  "-encoding", "utf8", // Option and arguments on same line
  "-Xfatal-warnings",  // New lines for each options
  "-deprecation",
  "-unchecked",
  "-language:implicitConversions",
  "-language:higherKinds",
  "-language:existentials",
  "-language:postfixOps"
)

ScalaTest

ScalaTestホーム

バージョン別ドキュメント