Both sides previous revisionPrevious revisionNext revision | Previous revision |
language:scala [2020/09/02 19:09] – [Type variance] 내용 추가 ledyx | language:scala [2021/03/24 08:18] (current) – [Command Line] 프로젝트 생성/배포 내용 보강 ledyx |
---|
https://www.scala-lang.org/download/ | https://www.scala-lang.org/download/ |
| |
* SBT (Scala Build Tools) | === SBT (Scala Build Tools) === |
Scala의 Ant/Maven/Gradle와 비교될 수 있음. 직접으로 프로젝트 생성, 배포 관여. | Scala의 Ant/Maven/Gradle와 비교될 수 있음. 직접으로 프로젝트 생성, 배포 관여. |
| |
| ==== Create templates ==== |
| |
| https://www.scala-sbt.org/1.x/docs/sbt-new-and-Templates.html |
| |
<sxh shell> | <sxh shell> |
# 생성 | sbt new scala/scala-seed.g8 |
sbt [Project Name] | </sxh> |
| |
| |
| ==== Fat Jar ==== |
| |
| https://github.com/sbt/sbt-assembly |
| |
| <sxh shell> |
# Build (Fat Jar 생성) | # Build (Fat Jar 생성) |
## build.sbt에 | ## build.sbt에 |
## addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.6") | ## addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.15.6") |
## 추가 필요 | ## 추가 필요 |
### 생성된 jar 위치 : target/scala-[version]/*.jar | ### 생성된 jar 위치 : target/scala-[version]/*.jar |
sbt assemblyty | sbt assembly |
| |
</sxh> | </sxh> |
| |
| |
* Scala Binaries (선택 사항) | |
| === Scala Binaries (선택 사항) === |
* REPL(scala), 단독 Compile(scalac)을 이용하기 위해 필요 | * REPL(scala), 단독 Compile(scalac)을 이용하기 위해 필요 |
| |
식별자 규칙 및 관례적 명명법 서술. | 식별자 규칙 및 관례적 명명법 서술. |
| |
* 연산자 정의(Operator Defination) Method와 암시적 변환([[language:scala#Implicit Conversions|Implicit Conversions]])는 간결하고 유연한 표현을 정의할 수 있지만, 잘못 사용하면 가독성을 떨어뜨리는 결과를 낳으니 주의가 필요하다. | * 연산자 정의(Operator Defination) Method와 암시적 변환([[language:scala#Implicit Parameters and Conversions|Implicit Parameters and Conversions]])는 간결하고 유연한 표현을 정의할 수 있지만, 잘못 사용하면 가독성을 떨어뜨리는 결과를 낳으니 주의가 필요하다. |
| |
| |
==== for-yield ==== | ==== for-yield ==== |
| |
<EXPRESSION>의 값을 Collection로 반환. | <EXPRESSION>의 값을 Collection로 반환. (//map// 과 같은 효과) |
| |
<code scala> | <code scala> |
==== Companion object ==== | ==== Companion object ==== |
| |
어떤 class **이름**이 같은 object. 그 피대상인 class는 "Companion class"라고 한다. Companion object와 [[language:scala#'apply' Method|'apply' Method]]를 이용하여 Companion class의 <fc red>**__"Factory Pattern"__**</fc>을 적용할 때 사용. | 어떤 class **이름**이 같은 object. 그 피대상인 class는 "Companion class"라고 한다. Companion object와 [[language:scala#'apply' Method|'apply' Method]]를 이용하여 Companion class의 [[design_pattern:factory_method_pattern|Factory Pattern]] 을 적용할 때 사용. |
이 때, object의 field들이 "private"으로 선언되어 있더라도 접근 가능. | 이 때, object의 field들이 "private"으로 선언되어 있더라도 접근 가능. |
| |
Type parameter를 **<fc red>덜 제한적</fc>**으로 만드는 방법. | Type parameter를 **<fc red>덜 제한적</fc>**으로 만드는 방법. |
타입 가변성(Type variance)은 Type parameter가 Base type이나 Sub type을 충족하도록 적응하는 방법을 지정한다. | 타입 가변성(Type variance)은 Type parameter가 Base type이나 Sub type을 충족하도록 적응하는 방법을 지정한다. |
| |
| |
|<100%>| | |<100%>| |
^ Scala ^ Java ^ 설명 ^ 예시 ^ | ^ Scala ^ Java ^ 설명 ^ 예시 ^ |
| T | T | Invariance (무공변성) | **X[T]**는 **X[T]**. X[T<sub>sub</sub>] 혹은 X[T<sup>super</sup>]가 X[T]를 대체할 수 없음. | | |
| +T | ? extends T | Covariance (공변성) | **X[T<sub>sub</sub>]**는 **X[T]**의 Sub type | | | +T | ? extends T | Covariance (공변성) | **X[T<sub>sub</sub>]**는 **X[T]**의 Sub type | |
| -T | ? super T | Contravariance (반공변성) | **X[T<sup>super</sup>]**는 **X[T]**의 Sub type | | | -T | ? super T | Contravariance (반공변성) | **X[T<sup>super</sup>]**는 **X[T]**의 Sub type | |
| | T | T | Invariance (무공변성) | **X[T]**는 **X[T]**. X[T<sub>sub</sub>] 혹은 X[T<sup>super</sup>]가 X[T]를 대체할 수 없음. | |
| |
* Effective Java에서 나오는 [[https://www.oracle.com/technetwork/server-storage/ts-5217-159242.pdf|PECS (Producer extends, Consumer super)]] 원리와 같은 개념. | * Effective Java에서 나오는 [[https://www.oracle.com/technetwork/server-storage/ts-5217-159242.pdf|PECS (Producer extends, Consumer super)]] 원리와 같은 개념. |
* 반환해야 하는(생산하는) 값이 Super type인데, 인자로 받은(제공하는) 값이 Sub type이면 Super type의 Method를 호출할 수 없음. | * 반환해야 하는(생산하는) 값이 Super type인데, 인자로 받은(제공하는) 값이 Sub type이면 Super type의 Method를 호출할 수 없음. |
* 이런 이유로 T1은 동등한 레벨의 타입이거나 상위 타입(Super type)이어야 한다. | * 이런 이유로 T1은 동등한 레벨의 타입이거나 상위 타입(Super type)이어야 한다. |
| * "상위 추상화 타입 -> 하위 구체화 타입" |
=== Invariance === | |
| |
무공변성. | |
| |
Type parameter의 기본값. Type-parameterized class의 Instance는 오직 같은 Parameterized type class만 호환된다. | |
| |
<sxh scala> | <sxh scala> |
class Item[A] | // https://github.com/deanwampler/programming-scala-book-code-examples/blob/master/src/main/scala/progscala3/objectsystem/variance/FunctionVariance.scala |
| |
class Person | class CSuper { def msuper() = println("CSuper") } |
class Employee extends Person | class C extends CSuper { def m() = println("C") } |
class HomeMinusEmployee extends Employee | class CSub extends C { def msub() = println("CSub") } |
| |
| |
object Practice extends App { | |
// Okay! | |
val p: Person = new Employee() | |
val i1: Item[Person] = new Item[Person]() | |
| |
| object AbsTypes extends App { |
| // 추상적인 것 -> 구체적인 것 |
| val f1: C => C = (c: C) => new C |
| val f2: C => C = (c: CSuper) => new CSub |
| val f3: C => C = (c: CSuper) => new C |
| val f4: C => C = (c: C) => new CSub |
| |
// Error! | // Error! |
val i2: Item[Person] = new Item[Employee]() | /** 인자로 C를 받도록 타입을 정의했는데, C를 상속받은 CSub를 인자로 받는다면 |
| * C가 알지못하는 Method가 호출될 수 있다! |
| */ |
| val f5: C => C = (c: CSub) => new CSuper |
} | } |
</sxh> | </sxh> |
| |
| |
=== Covariance === | |
| |
공변성. | = Abstract types = |
| |
Type parameter가 부모 Type으로 변할 수 있는 성질. (Sub parameterized-type → Base parameterized-type) Type parameter 앞에 **+**를 붙인다. | https://docs.scala-lang.org/tour/abstract-type-members.html |
| |
<sxh scala ; highlight: [1]> | <sxh scala ; highlight:[7,8,13,15,21,23]> |
class Item[+A] | |
| |
class Person | |
class Employee extends Person | |
class HomeMinusEmployee extends Employee | |
| |
object Practice extends App { | |
// Okay! | |
val p: Person = new Employee() | |
val i1: Item[Person] = new Item[Person]() | |
| |
// Okay! | |
val i2: Item[Person] = new Item[Employee]() | |
} | |
</sxh> | |
| |
| |
=== Contravariance === | |
| |
반공변성. | |
| |
| |
= Abstract types = | |
| |
<sxh scala ; highlight:[7,8,13,18]> | |
import java.io._ | import java.io._ |
import scala.io.Source | import scala.io.Source |
// 위 소스를 응용한 예제 | // 위 소스를 응용한 예제 |
abstract class BulkReader { | abstract class BulkReader { |
type In // 구체적인 타입을 지정하지 않음. | type In // 구체적인 타입을 지정하지 않음. |
val source: In // 바로 위에서 지정한 Type인 "In"을 사용 | val source: In // 바로 위에서 지정한 Type인 "In"을 사용 |
def read: String | def read: String |
} | } |
| |
class StringBulkReader(val source: String) extends BulkReader { | class StringBulkReader |
type In = String | (val source: String) // 추상 타입의 실질 타입 정의 |
| extends BulkReader { |
| type In = String // 추상 타입 구체화 |
override def read: String = source | override def read: String = source |
} | } |
| |
class FileBulkReader(val source: File) extends BulkReader { | class FileBulkReader |
type In = File | (val source: File) // 추상 타입의 실질 타입 정의 |
| extends BulkReader { |
| type In = File // 추상 타입 구체화 |
override def read: String = { | override def read: String = { |
val source1 = Source.fromFile(source) | val source1 = Source.fromFile(source) |