Scala Language
형질
수색…
통사론
- 형질 ATrait {...}
- 클래스 AClass (...)는 ATrait {...}를 확장합니다.
- class AClass는 ATclass와 함께 BClass를 확장합니다.
- AClass 클래스는 ATrait와 BTrait를 확장합니다.
- class AClass는 CTrait와 함께 BTrait와 함께 ATrait를 확장합니다.
- ATrait는 BTrait를 확장시킨다.
특성을 이용한 스택 가능 수정
형질을 사용하여 형질을 사용하여 클래스의 메소드를 수정할 수 있습니다.
다음 예는 형질을 어떻게 쌓을 수 있는지 보여줍니다. 형질의 순서가 중요합니다. 다른 특성의 순서를 사용하여 다른 행동이 성취됩니다.
class Ball {
def roll(ball : String) = println("Rolling : " + ball)
}
trait Red extends Ball {
override def roll(ball : String) = super.roll("Red-" + ball)
}
trait Green extends Ball {
override def roll(ball : String) = super.roll("Green-" + ball)
}
trait Shiny extends Ball {
override def roll(ball : String) = super.roll("Shiny-" + ball)
}
object Balls {
def main(args: Array[String]) {
val ball1 = new Ball with Shiny with Red
ball1.roll("Ball-1") // Rolling : Shiny-Red-Ball-1
val ball2 = new Ball with Green with Shiny
ball2.roll("Ball-2") // Rolling : Green-Shiny-Ball-2
}
}
super
는 두 특성 모두에서 roll()
메소드를 호출하는 데 사용됩니다. 이 방법으로 만 스택 적 수정을 수행 할 수 있습니다. 스택 가능 수정의 경우, 메소드 호출 순서는 선형화 규칙에 의해 결정됩니다.
특성 기본 사항
이것은 스칼라에서 가장 기본적인 특성의 버전입니다.
trait Identifiable {
def getIdentifier: String
def printIndentification(): Unit = println(getIdentifier)
}
case class Puppy(id: String, name: String) extends Identifiable {
def getIdentifier: String = s"$name has id $id"
}
Identifiable
할 수있는 특성에 대해 수퍼 클래스가 선언되지 않으므로 기본적으로 AnyRef
클래스에서 확장됩니다. Identifiable
에는 getIdentifier
에 대한 정의가 없기 때문에 Puppy
클래스는이를 구현해야합니다. 그러나 Puppy
는 Identifiable
에서 printIdentification
구현을 상속받습니다.
REPL에서 :
val p = new Puppy("K9", "Rex")
p.getIdentifier // res0: String = Rex has id K9
p.printIndentification() // Rex has id K9
다이아몬드 문제 해결
다이아몬드 문제 또는 다중 상속은 Java 인터페이스와 유사한 Traits을 사용하여 Scala에서 처리합니다. 특성은 인터페이스보다 유연하며 구현 된 방법을 포함 할 수 있습니다. 이것은 다른 언어의 mixin 과 비슷한 특성을 만듭니다.
스칼라는 여러 클래스의 상속을 지원하지 않지만 사용자는 단일 클래스에서 여러 특성을 확장 할 수 있습니다.
trait traitA {
def name = println("This is the 'grandparent' trait.")
}
trait traitB extends traitA {
override def name = {
println("B is a child of A.")
super.name
}
}
trait traitC extends traitA {
override def name = {
println("C is a child of A.")
super.name
}
}
object grandChild extends traitB with traitC
grandChild.name
여기 grandChild
는 traitB
와 traitC
모두에서 상속을 traitA
. traitA
는 traitA
상속받습니다. 출력 (아래)은 어떤 메소드 구현이 먼저 호출되는지를 결정할 때 우선 순위를 보여줍니다 :
C is a child of A.
B is a child of A.
This is the 'grandparent' trait.
super
가 class
또는 trait
메서드를 호출하는 데 사용되는 경우 호출 계층 구조를 결정하기 위해 선형화 규칙이 적용됩니다. grandChild
선형화 순서는 다음과 같습니다.
grandChild -> traitC -> traitB -> traitA -> AnyRef -> Any
다음은 또 다른 예입니다.
trait Printer {
def print(msg : String) = println (msg)
}
trait DelimitWithHyphen extends Printer {
override def print(msg : String) {
println("-------------")
super.print(msg)
}
}
trait DelimitWithStar extends Printer {
override def print(msg : String) {
println("*************")
super.print(msg)
}
}
class CustomPrinter extends Printer with DelimitWithHyphen with DelimitWithStar
object TestPrinter{
def main(args: Array[String]) {
new CustomPrinter().print("Hello World!")
}
}
이 프로그램은 다음을 인쇄합니다.
*************
-------------
Hello World!
CustomPrinter
선형화는 다음과 같습니다.
CustomPrinter -> DelimitWithStar -> DelimitWithHyphen -> Printer -> AnyRef -> Any
선형화
스택 가능 수정의 경우 스칼라는 클래스 및 특성을 선형 순서로 정렬하여 메서드 호출 계층을 결정합니다.이를 선형화라고 합니다. 선형화 규칙은 super()
를 통한 메소드 호출과 관련된 메소드 에만 사용 됩니다 . 이를 예로 들어 보겠습니다.
class Shape {
def paint (shape: String): Unit = {
println(shape)
}
}
trait Color extends Shape {
abstract override def paint (shape : String) {
super.paint(shape + "Color ")
}
}
trait Blue extends Color {
abstract override def paint (shape : String) {
super.paint(shape + "with Blue ")
}
}
trait Border extends Shape {
abstract override def paint (shape : String) {
super.paint(shape + "Border ")
}
}
trait Dotted extends Border {
abstract override def paint (shape : String) {
super.paint(shape + "with Dotted ")
}
}
class MyShape extends Shape with Dotted with Blue {
override def paint (shape : String) {
super.paint(shape)
}
}
선형화는 뒤에서 앞으로 일어난다. 이 경우,
First
Shape
는 다음과 같이 선형화됩니다.Shape -> AnyRef -> Any
그런 다음
Dotted
가 선형화됩니다.Dotted -> Border -> Shape -> AnyRef -> Any
다음 줄은
Blue
입니다. 일반적으로Blue
의 선형화는 다음과 같습니다.Blue -> Color -> Shape -> AnyRef -> Any
왜냐하면
MyShape
의 선형화 ( Step 2 )까지는Shape -> AnyRef -> Any
가 이미 나타Shape -> AnyRef -> Any
때문입니다. 따라서 무시됩니다. 따라서Blue
선형화는 다음과 같습니다.Blue -> Color -> Dotted -> Border -> Shape -> AnyRef -> Any
마지막으로
Circle
이 추가되고 최종 선형화 순서가 다음과 같이됩니다.원 -> 파랑 -> 색상 -> 점선 -> 테두리 -> 모양 -> AnyRef -> Any
이 선형화 순서는 super
클래스가 어떤 클래스 나 특성에서 사용될 때 메소드의 호출 순서를 결정합니다. 오른쪽에서부터 첫 번째 메소드 구현이 선형화 순서로 호출됩니다. new MyShape().paint("Circle ")
가 실행되면 다음과 같이 인쇄됩니다.
Circle with Blue Color with Dotted Border
선형화에 대한 자세한 내용은 여기를 참조하십시오 .