scala 기본(클래스)

스칼라

  1. 변수
  2. 함수

이번엔 클래스에 대해 알아보자.
일단 클래스의 기본형태를 보자

class MyClass {

}

요거다. 자바랑 비슷하다.
그럼 상세하게 더 보자.

class MyClass(id: Long, name: String) {

  def this(id:Long) = this(id,"No name")

  def getName = name

  def getId = id

  override def toString = s"id = $id name = $name"
}

보자 흠..
일단 MyClass옆에 있는저건 생성자다.
저렇게 클래스 생성할 수 있다.
그리고 그 밑은 id만 있는 생성자다. 보조 생성자?
그리고 그 밑은 흔히 말하는 getter 일반적은 function이다.
그리고 자바와 다른점은 override 어노테이션이 아니라 예약어 인듯하다.
그럼 한번 클래스를 생성해보자.

val myClass = new MyClass(1L,"wonwoo")
println(myClass)
println(myClass.getName)

id = 1 name = wonwoo
wonwoo

다음 소스도 보자

class MyClass(val id: Long, val name: String) {

  private val number = 1000

  def this(id:Long) = this(id,"No name")

  def getName = name

  def getId = id

  def getNumber = number

  def setNumber(number:Int) = this.number = number

  override def toString = s"id = $id name = $name"
}

자바와 마찬가지로 private 으로 접근제어도 가능하다.
그리고 number는 val이 때문에 setNumber 컴파일 에러가 날것이다.
앞서 설명 했듯이 val는 자바의 final이라 생각하면 빠르다.
자바 개발자를 위한 스칼라 공부인듯 하네..
아 저기 보인 toString 함수를 보자.
우리가 자바를 사용할때 불편점이 있었다. 위와 같은 코드를 만들때 "id = " + id + "name = " + name 이런식을 만들었다.
보기만 해도 불편하다. 불편한 것도 있지만 자바에서 저코드는 비효율적이다. 물론 저렇게 몇개 안되는 연산은 상관없지만
많은 연산을 할 경우 String을 계속 생성하기 때문에 메모리상 비효율적이다.
그건 그렇고 일단 보기에도 불편하다.
하지만 스칼라는 앞에 s만 붙이고 나면 효율적으로 이어 나갈 수 있다. 간편해서 좋다.
클래스이야기 하다 삼천포로 빠졌네.

다시 class 로 가자

class Animal(var name: String) {

  def getName = name

  override def toString = s"name is $name"
}

class Dog(name: String, sound: String) extends Animal(name: String) {

  def getSound = sound

  override def toString = s"my name is $name and sound $sound"
}

상속이다. 객체지향언어라면 상속이 있다. 스칼라도 있다.
개념은 자바와 같다. 자바 개발자라면 생성자를 만드는게 약간 어색하지만 그래도 이해는 된다.
마찬가지로 추상클래스도 있다.

abstract class Pizza{

  def order

  def orderPizza = {
    order
    prepare
    bake
  }
  def prepare = println("prepare")

  def bake = println("bake")
}

class ChicagoPizza extends Pizza{
  override def order: Unit = println("ChicagoPizza")
}

class LAPizza extends Pizza {
  override def order: Unit = println("LAPizza")
}

간단하게 만들어봤다.
개념은 자바와 동일한듯 하다.
abstract 메소드만 필수적으로 구현 해주면 된다.

클래스 자체는 어렵지 않은 듯 하다. 자바와 비슷하기 때문에 그렇게 어렵게 느껴지짆 않는다.
다음 시간에 스칼라의 인터페이스라 불리는 trait에 대해 알아보자
시간이 되면 class도 더 알아볼 예정이다.

scala 기본(함수)

스칼라

  1. 변수

이번엔 함수에 대해 알아보자.

def add(x: Int, y: Int): Int = {
  x + y
}

기본적인 함수 형태다. 흠
add 안에 있는건 파라미터고 그 밖에 Int는 리턴 타입이다.
int 파라미터를 두개를 받아서 int로 리턴하는거다.
일단 눈에 보이는건 return 이라는게 명시적으로 없다.
자동으로 마지막줄 실행 결과가 return 된다고 한다.
추론을 아주 열심히 하군.

저기서 생략 할 수 있는게 더 있다.
일단 리턴타입을 생략 가능하다.

def add(x: Int, y: Int) = {
  x + y
}

또한 메소드 바디의 { }를 제거 할 수 있다.

def add(x: Int, y: Int) =  x + y

와우!!

def main(args: Array[String]) {
  println(add(10,20))
}

한번 출력 해보자
다 잘된다.

한번 파라미터 타입도 생략해보자

def add(x, y) =  x + y

흠 안된다.
하지만 자바의 제네릭 처럼 어떠한 값도 상관 없다면 이런식으로 하면 된다.

def print(x : Any) = println(x)

호출 해보자 잘되나

print("hello")
print(999)

다음으론 익명함수를 살펴보자

(x:String) => println(x))("hello")

흠 감이 안잡히는 사람도 있을 것이다.

(() => print("hello"))()

이렇게 생각하면 조금 나을듯 하다.
웹 서버 개발자라면 2개의 언어를 무조건 알고 있다. 딱히 심도있게 배우지는 않았지만 그래도 어느정도는 아는게 자바스크립트다.
잘은 몰라도 어떻게 쓰는지는 아는? 그런정도?
자바스크립트에서 자주 사용하던 익명함수를 생각해보자

(function() {
    //...
}());

위의 스칼라 코드와 비슷하지 않은가?
그렇게 생각하면 조금더 빨리 와닿지 않을까 생각해 추가적으로 설명해놨다.

이번엔 약간 헷갈리는 _(언더바) 이다. 일단 코드부터보자

println((1 to 3).map(_ * 2))

일단 _(언더바)는 args 값이라고 한다.
흠…. map에는 한개의 파라미터가 존재하니까 _(언더바)가 하나 인거는 알겠다.

파라미터 값이라 했으니 일반 function에도 될듯 싶었다.
그래서 아까 만든 add 함수에 넣어봤다.

val add1 = add(_, 1)

일단 컴파일은 잘된다.
하지만 돌려보면 에러가 발생한다.

Error:(19, 20) missing parameter type for expanded function ((x$2) => add(x$2, 1))
    val add1 = add(_, 1)
                   ^

흠 저게 익명함수처럼 컴파일이 되네..
어찌됬건 _(언더바)의 타입이 없다고 하는 거 같다.
그래서 정의 해줘야된다.

val add1 = add(_: Int, 1)
println(add1(10))

그럼 제대로 나온다.
_(언더바)의 값을 알 수 없으니 다시 function을 리턴 하는 모양이다. 그래서 아래에서 다시 호출 하였다.

이번엔 자바8에서 흔히 쓰이는 익명함수다.

(1 to 3).map(i => i * 2).foreach(print)

자바랑 같기에 딱히 설명할 필요는 없는거 같다.

마지막으로 *

(1 to 3).map(2*).foreach(print)

흠 이거는 _ * 2 와 같다고 생각할 수 있다.

약간 새로운 문법들이 있어 낯설긴 하지만
재밌고 신기한 언어다.

흠 다음엔…뭘하지..
클래스와 오브젝트에 대해 알아보자!

scala 기본(변수)

스칼라

예전부터 배우고 싶은 언어가 있었는데 그게 바로 스칼라다.
괜찮은아이 같아 조금씩 한번 살펴 보겠다.
필자도 처음 공부하는거라 틀릴 수도 있으니 주의!
스칼라는 모든것이 객체이다. 함수까지 객체다. 그래서 약간 헷갈리긴 한다.
그래도 한번 천천히 살펴보자!

일단 제일 기본인 hello world 를 찍자!

object HelloWorld {
  def main(args: Array[String]) {
    println("Hello World")
  }
}

Hello World

나왔다.
일단 보니까 자바랑 비슷하다. 어쩔수 없나부다
그리고 여기서 중요한 사실은 ;(세미콜론) 이 없다는거다.
약간 어색하지만 보기는 좋다.
근데 자꾸 ;을 찍는다 습관이다.;;

첫 번째로 변수에 대해 알아보자.
변수는 두가지가 있다.
상수와 변수
상수는 val 변수는 var 타입 추론을 열심히 하는 모양이다.
그래도 자바엔 lombok 이 있다. 자바의 val는 약간 이상하서 잘 안쓴다. 그래도 좋은 라이브러리다!

var x = 1
x = 10
//compile error
x = "Hello world"
val y = 100
//compile error
y = 200

변수 x를 1로 선언했다. 그리고나서 10으로 변경 했다 var 선언했기 때문에 가능하다. 그리고나서 다시 Hello world로 바꾸었다.
에러가 난다. 오오 타입추론 아주 좋다.
그리고 val y 로 선언했다. 그리고나서 값을 바꾸어봤다. 역시 에러다. 상수이기 때문에.
val는 java의 fianl 이라고 생각하면 된다.

이번엔 문자열을 반복하는 메소드를 만들어보자
자바같은경우는 아마도 for문으로 했을 가능성이 있을 것이다.
스칼라를 보자

println("string" * 3)

끝이다. 정말 간단하다.

배열 선언을 보자

val list = List(1, 2, 3, 4, 5)
println(list)

아래와 같이 선언 할 수 도 있다.

(1 :: 2 :: 3 :: Nil).foreach(println)

다음은 map을 보자

val map = Map("key" -> 1, "key1" -> 2)
val key: Option[Int] = map.get("key")
println(key)

자바와 비슷하다.
Option이라는게 눈에 띈다. 아 물론 생략 가능하다.
이건 자바8에도 있는 기능같다
null point 를 방지하기 위한 객체 인듯싶다.

스칼라엔 Seq 라는 trait 가 있다.

val seq: Seq[Int] = Seq(1,2,3,4,5)
println(seq)

순서가 있다고 한다.
하지만 return 은 List 로 한다.
List 는 Seq 를 상속하고 있다.

sealed abstract class List[+A]() extends scala.collection.AbstractSeq[A] with scala.collection.immutable.LinearSeq[A] ... 

보니까 새로운 키워드가 많다.
나중에 천천히 살펴 보겠다.
일단 처음으로 scala를 배워 보았다. 나름 재밌는 언어 같다.
다음엔 함수에 대해 알아보겠다.