without haste but without rest

Scala Book memo 본문

ProgrammingLanguage/Scala

Scala Book memo

JinungKim 2022. 2. 17. 13:52
Scala Book

Summary

스칼라의 컨셉과 언어의 목적에 대해서 간단히 살펴보고 loop, condition, class, method 등을 빠르게 훑는다.


Concept

Scalable한 언어라 'Scala' 라는 이름을 붙였다. JVM 기반 언어이며 주로 데이터 처리를 위한 목적으로 많이 사용한다. 

 

스칼라는 스칼라로 쓰였다는데 이 내용이 정확히 의미하는 바에 대해서 찾아보기.


val & var

val a = 1
var b = 1

val은 value로 변수를 한 번 선언하면 값을 변경할 수 없다.

var는 variable로 변수를 선언하고 난 이후에 변경할 수 있다.


Object

오브젝트는 자바의 static class member와 유사하다. 스칼라에서는 정적 변수가 없다. 대신에 object를 이용해서 싱글톤 객체를 생성한다. 단일 객체만 존재하는 클래스라고 할 수 있다.

 

Understanding class and object in scala

I'm very new to scala and now I have to work on a project which is written both in scala and java. I came across with this-like construction: class SomeType{ //... } trait Trait1 extends scala.

stackoverflow.com

 

오브젝트 내에서 자바처럼 main 메서드를 통해 프로그램을 실행할 수 있다.

object Hello {
  def main(args: Array[String]) = {
      greeting("Jinung")
  }
  def greeting(name: String): Unit = {
    println("Hello " + name)
    
  }
}

 

App 상속

더욱 간편한 방법으로 스칼라 북에서는 버전2라고 소개하고있다.

object Hello2 extends App {
  greeting("Jinung")
  
  def greeting(name: String): Unit = {
    println("Hello " + name)
  }
}

 


Loop

for 문에서 괄호를 쓰는데, <- 문자를 추가해주어야 한다. 

scala> val nums = Seq(1,2,3)
nums: Seq[Int] = List(1, 2, 3)

scala> for (n <- nums) println(n)
1
2
3

 

응용 버전

object Main extends App{
  for (number <- 0 to 10 by 2) println(number)
}

number 변수에 0부터 10까지 단위는 2로 건너뛰며 변수를 전달한다. (이때 파이썬처럼 이터레이터 객체를 생성하는지는 잘 모르겠다.)

to는 많은 프로그래밍 랭귀지에서 사용하는 미만 범위가 아니라 포함이다. 미만으로 사용하고자 하는 경우에는 until을 사용한다. 

 

While

object Main extends App{
  var num = 0
  while (num < 10) {
    println(num)
    num = num + 1
  }
}

Condition

자바의 조건문과 형태가 같다.

if (test1) {
    doX()
} else if (test2) {
    doY()
} else {
    doZ()
}

Class

Basic Class

class Person(var firstName: String, var lastName: String)

val p = new Person("Bill", "Panner")

 

필드에 접근하는 방법

자바의 경우 getter, setter를 별도로 구현하는 게 일반적인 방법인데, 스칼라는 그냥 바로 접근하게 하나보다.

scala> p.firstName = "William"
p.firstName: String = William

scala> p.lastName = "Bernheim"
p.lastName: String = Bernheim

 

 

Example

object Hello2 extends App {
  val p = new Person("Jinung", 27)
  val name = p.showName()
  println(name)
  
}

class Person(val name: String, var age: Int) {
  def getName(): String = {
    name
  }
  def getAge(): Int = {
    age
  }
}

Method

클래스 내부에서만 선언하는 게 아닌데, 왜 메서드인지 잘 모르겠다.

모든 변수가 객체라서 그런것인지 더 확인해보기

 

간단한 메서드

def addThenDouble(a: Int, b: Int): Int = {
    val sum = a + b
    val doubled = sum * 2
    doubled
}

문법이 조금 헷갈릴 수 있는 부분인데 addThenDouble 함수는 Int 타입을 반환한다. 이때 메서드의 내부 블록에서 마지막에 등장하는 doubled가 반환할 값이다. (스칼라는 return이 없다. 충 격)

 

 

아래와 같은 형태로도 선언할 수 있다.

def double(a: Int) = a * 2

double(a: Int): 메서드 명과 변수 타입 선언

= a * 2 : 변수에 2를 곱한 값을 리턴 


Trait & Abstact Class

Trait은 인터페이스 목적으로 사용할 수 있다. Abstact Class는 자바의 그 추상 클래스가 맞다.

차이점은 Trait은 Constructor 변수를 선언하지 못한다. 

*인터페이스와 추상 클래스의 차이점

인터페이스는 모든 메서드가 추상 메서드. 추상 클래스는 일부분만 추상 메서드일 수 있다. 

추상 클래스는 이를 상속 받는 하위 클래스가 추상 메서드를 확장해서 사용할 목적이다.

반면 인터페이스는 껍데기만 규정해서 함수의 구현을 강제하는 목적으로 사용한다.

 

Trait Example

trait TailWagger {
    def startTail(): Unit
    def stopTail(): Unit
}

Java Style

public interface TailWagger {
    public void startTail();
    public void stopTail();
}

 

Extending a Trait

trait TailWagger {
    def startTail(): Unit
    def stopTail(): Unit
}

class Dog extends TailWagger {
    // the implemented methods
    def startTail(): Unit = println("tail is wagging")
    def stopTail(): Unit = println("tail is stopped")
}

 Trait은 여러 개도 상속할 수 있다.


Abstact Class

스칼라의 추상 클래스 컨셉은 자바의 추상 클래스와 유사하다. 그런데 스칼라에서는 트레잇의 기능이 막강해서 추상 클래스를 쓸 일이 거의 없다. 스칼라에서 추상 클래스를 쓰는 경우는 다음과 같다.

 

  • 컨스트럭터를 필요로 하는 베이스 클래스 생성을 원하는 경우
  • 스칼라 코드를 자바에서도 호출하고자 하는 경우

 

다음과 같이 트레잇은 컨스트럭터 파라미터를 허용하지 않는다.

// this won’t compile
trait Animal(name: String)

 

그러므로 컨스트럭터 파라미터를 사용하고자 하는 경우 추상 클래스를 사용한다.

abstract class Animal(name: String)

 

Extending Example

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

 

 

여기서 의문

트레잇은 파라미터를 허용하지 않는데 이러한 경우, 트레잇을 상속하는 다른 클래스는 리스코브 원칙을 만족시킬 수 있는가?


Pure Function

함수가 함수 외부에 무언가에 의존하지 않고 작동하는 것을 Pure Function이라고 부른다.

 


Scala Collections

 

 


스파크 학습 하면서 필요한 부분은 계속해서 업데이트...

Comments