2017-12-07 27 views
0

아마 내가

case class test { 
        a:string 
        b: string 
        c: Int 
        d: Int } 


var temp = List(test("lol","lel",1,2)) 
var total = List(test) 

total = total:::temp //this doesn't work because temp is of type [test] while total is of type [test.type] 

나는 차이를 이해하지 않는 다음 한 예상 목록 스칼라을 준수하지 않습니다. 이것을 사용하고자하는 이유는 요소가 루프에 조건부로 추가되는 실행 목록을 갖고 싶기 때문입니다. 따라서이 경우 total은 처음에는 test 개의 개체를 사용하는 빈 목록이어야합니다. 어떻게해야합니까?

모든 의견을 환영합니다.

답변

1

먼저 스칼라에 대한 몇 가지 기본 사항을 설명하겠습니다.

스칼라에서는

scala> class Demo(a: String, b: Int) { 
| def stringify: String = a + " :: " + b 
| } 
// defined class Demo 

당신은 그 class의 인스턴스를 생성하는 데 사용되는 스칼라에 주어진 청사진으로 class 생각할 수있는, 다음과 같이 클래스를 정의합니다. 여기에 class Demo의 모든 인스턴스에는 StringbInt이고 하나의 방법이 stringify이고 두 번째 속성이 a이고 String을 반환합니다. 여기

scala> val demo1 = new Demo("demo1", 1) 
// demo1: Demo = [email protected] 

scala> demo1.getClass 
// res0: Class[_ <: Demo] = class Demo 

demo1classDemo의 인스턴스이며 typeDemo있다.

스칼라에는 특별히 생성 된 내부 클래스의 인스턴스 인 object의 개념이 있습니다.

scala> object OtherDemo { 
| val a: Int = 10 
| } 
// defined object OtherDemo 

scala> DemoObject.getClass 
// res2: Class[_ <: OtherDemo.type] = class OtherDemo$ 

여기 OtherDemo는 특별히 class OtherDemo$ 생성의 인스턴스 만하고 type OtherDemo.type을 보유한다.

그리고는 스칼라

scala> case class AnotherDemo(a: Int) 
// defined class AnotherDemo 

이 만들어집니다에 case class있다뿐만 아니라 classAnotherDemo하지만 우리는 동반자 개체를 호출 또한 objectAnotherDemo. 어느

class AnotherDemo(a: Int) 

object AnotherDemo { 

    def apply(a: Int): AnotherDemo = new AnotherDemo(a) 

    def unapply(anotherDemo: AnotherDemo): Option[Int] = Some(anotherDemo.a) 

    // And many more utility functions 
} 

우리는 class AnotherDemocompanion object으로이 object AnotherDemo를 호출하는 것과 동일합니다. 클래스 이름은 대문자로 시작해야 스칼라에서 우리는 두 가지 방법으로 AnotherDemo의 인스턴스를 만들 수 있습니다

, 또한

// By using new keyword, as we can do for any class 
scala> val anotherDemo1 = new AnotherDemo(1) 
// anotherDemo1: AnotherDemo = AnotherDemo(1) 

// Or we can use `apply` method provided by companion object 
scala> val anotherDemo2 = AnotherDemo(2) 
// anotherDemo2: AnotherDemo = AnotherDemo(2) 

scala> anotherDemo1.getClass 
// res6: Class[_ <: AnotherDemo] = class AnotherDemo 

scala> anotherDemo2.getClass 
// res7: Class[_ <: AnotherDemo] = class AnotherDemo 

scala> AnotherDemo.getClass 
// res8: Class[_ <: AnotherDemo.type] = class AnotherDemo$ 

. 이렇게하면 작은 글자로 시작해야하는 인스턴스 변수와 쉽게 구별 할 수 있습니다. 이것은 혼란을 피하는 데 도움이됩니다.

이제는 a: String이 아니고 a: string이 아닌 것으로 가정합니다.그것은 실제로 동일합니다

scala> var temp = List(Test("lol","lel",1,2)) 
// temp: List[Test] = List(Test(lol,lel,1,2)) 

이제

scala> case class Test(
|  a: String, 
|  b: String, 
|  c: Int, 
|  d: Int 
| ) 
// defined class Test 

, 당신이 쓰는,

var temp = List.apply(Test.apply("lol","lel",1,2)) 

또는

val test1 = Test.apply("lol","lel",1,2) 
var temp = List.apply(test1) 

Test.applyTest하지 요입니다 ur class Test 그러나 companion object Test. 그리고 Test.apply를 호출하면 마지막으로 ListTest의 인스턴스를 포함 List[Test]type의를 얻을 수 List.apply에 전달되는 class Test의 인스턴스를 반환합니다.

는하지만

scala> var total = List(Test) 
// total: List[Test.type] = List(Test) 

당신은 Listcompanion objectTest의를 포함하는 유형 List[Test.type]의 작성이를 쓸 때.

초점 total: List[Test.type] 부분에 ...이 total 그것이 value/instanceList[Test.type]type의 가리 할 것을 의미하고, 무엇을 가리 키도록 거부 할 typeList[Test.type]variable 것을 의미한다.

... 지금이 작업을 수행하려고하는,에 해당

total = total ::: temp 

, 실제로

val x = total ::: temp 
total = x 

,

val x = temp.:::(total) 
total = x 

지금이 val x = total ::: temp보고 ,

scala> val x = total ::: temp 
// x: List[Serializable] = List(Test, Test(lol,lel,1,2)) 

너는이 xList[Serializable] 인 것을 본다. 당신이 total = x을 시도 할 때, 당신은 오류 다음 totalList[Test.type]이 필요하지만 당신은 그것을 List[Serializable]을 제공하는 것을 의미

scala> total = x 
// <console>:13: error: type mismatch; 
// found : List[Serializable] 
// required: List[Test.type] 
//  total = x 
//    ^

을 얻을 것이다.

0

List(test) 대신 total = List.empty[test]을 찾고 있습니다. 전자는 List[test] 유형의 빈 목록을 만듭니다. 후자는 List[test.type] (test.typetest과 동일하지 않습니다. 이는 test의 인스턴스 유형을 나타내는 자체 객체입니다.

또한 var을 사용하지 마십시오. 그들은 사악하고 실제로 99 %의 유스 케이스에서 스칼라에 필요하지 않습니다.다른 1 %를 자신있게 구별 할 수있을 정도로 언어를 파악할 때까지 키워드가 전혀 존재하지 않는 것처럼 행동하십시오.

0

이 할 때 :

var total = List(test)

당신은 객체 테스트를 초기화하지 않는, 즉 목록의 유형 Test.type 왜, 당신은 단지 개체에 대한 템플릿의 목록을 만드는입니다 .

이 대신 수행 할 때 var temp = List(test("lol","lel",1,2))

요는 (이 경우 클래스, 테스트) 템플릿을 인스턴스화 개체 때문에 온도의 유형 List[Temp]입니다 있습니다.

그래서 만약 당신이 뭔가를 할 경우 :

val template = Test 그런 다음 t의 유형은 Test.type

입니다 그리고 당신은 다음과 같이 template에서 개체 테스트를 인스턴스화 할 수 있습니다 :

val instantiated = template("lol","lel",1,2)

귀하의 예에서 볼 수 있듯이 total 변수는 인스턴스를 만들 수있는 템플릿 목록 일뿐입니다 변수가 temp 인 변수는 Test 유형의 객체 목록입니다.

유형 테스트의 객체의 빈 목록을 만들려면 당신은 할 필요가 :

val t: List[Test] = List.empty

는 그런 다음에 따라이 목록

0

에 (유형 Test의) 모든 개체를 추가 할 수 있습니다 설명 ('루프에서 요소를 조건부로 추가 할 수있는 실행 목록이 필요합니다.), 일부 이해 관계자가 Test 개체를 가져 와서 목록에 넣고 싶지만 특정 조건을 충족하는 경우에만 이해할 수 있습니다. 우리는이 요구 사항을 방법으로 표현할 수 있습니다. 편의상 우리는 Test 동반자 개체에 메서드를 넣을 것입니다. 컴패니언 개체는 개체를 인스턴스화 할 필요없이 사용할 수 있어야하는 것들을 넣을 수있는 장소입니다.

case class Test(a: String, b: String, c: Int, d: Int) 

object Test { 
    /** 
    Returns a list of `Test` objects that pass the given criteria. 

    @param tests some source of tests that we can loop over one at a 
    time. 
    @param condition checks whether a `Test` object should go into our 
    output list. 
    */ 
    def runningList(
    tests: Iterable[Test])(condition: Test => Boolean): List[Test] = 
    tests.filter(condition).toList 
} 

당신은 (예를 들어)처럼 사용할 수 있습니다 : 당신이 여기에서 볼 수 있듯이

Test.runningList(testsSource) { test => test.c > 0 && test.d < 100 } 

, 나는 반복 가능 객체처럼, 몇 스칼라 기능을 사용했습니다과 목록 변환 방법, 멀티 파라미터 유효 리스트 메소드, 퍼스트 클래스 함수, last-argument DSL과 같은 함수 등이 있습니다. 이 주제들에 대해 더 궁금한 점이 있다면 스칼라 튜토리얼을 추천한다.