IT박스

스칼라에서 def, val 및 var 사용

itboxs 2020. 6. 9. 22:23
반응형

스칼라에서 def, val 및 var 사용


class Person(val name:String,var age:Int )
def person = new Person("Kumar",12)
person.age = 20
println(person.age)

이 코드 행 은 성공적으로 실행 12되었음에도 불구하고 출력 person.age=20됩니다. 나는 이것이 def in을 사용했기 때문에 발생한다는 것을 알았습니다 def person = new Person("Kumar",12). var 또는 val을 사용하면 출력은 20입니다. 나는 scala의 기본값이 val임을 이해합니다. 이:

def age = 30
age = 45

... 기본적으로 val이므로 컴파일 오류가 발생합니다. 왜 위의 첫 번째 줄이 제대로 작동하지 않고 오류가 발생하지 않습니까?


스칼라에는 세 가지 방법으로 정의 할 수 있습니다.

  • def방법을 정의
  • val고정 값을 정의 합니다 (수정할 수 없음)
  • var변수를 정의 합니다 (수정 가능)

코드를 보면 :

def person = new Person("Kumar",12)

이것은라는 새로운 방법을 정의합니다 person. 이 메소드 ()는 매개 변수가없는 메소드로 정의되므로이 메소드를 호출하지 않아도 호출 할 수 있습니다 . 빈 빈 메소드의 경우 '()'를 사용하거나 사용하지 않고 호출 할 수 있습니다. 당신이 단순히 쓰는 경우 :

person

그런 다음이 메소드를 호출합니다 (반환 값을 지정하지 않으면 버려집니다). 이 코드 줄에서 :

person.age = 20

먼저 person메서드를 호출하고 반환 값 (class 인스턴스 Person)에서 age멤버 변수를 변경합니다 .

그리고 마지막 줄 :

println(person.age)

여기서 person메소드를 다시 호출하여 클래스의 새 인스턴스 Person( age12 설정)를 리턴합니다 . 다음과 같습니다 :

println(person().age)

def , valvar 사이의 Scala에 존재하는 구별로 시작합니다 .

  • def- 오른쪽 내용에 대한 불변 레이블정의합니다.이 내용은 느리게 평가되며 이름으로 평가됩니다.

  • val- 값으로 평가되는 즉시 / 즉시 평가 되는 오른쪽 컨텐츠에 대한 불변 레이블정의합니다 .

  • VAR은 - 정의 변경 가능한 변수 , 초기 평가 오른쪽의 내용으로 설정합니다.

예, def

scala> def something = 2 + 3 * 4 
something: Int
scala> something  // now it's evaluated, lazily upon usage
res30: Int = 14

예, val

scala> val somethingelse = 2 + 3 * 5 // it's evaluated, eagerly upon definition
somethingelse: Int = 17

예, var

scala> var aVariable = 2 * 3
aVariable: Int = 6

scala> aVariable = 5
aVariable: Int = 5

위와 같이 defval의 레이블은 재 할당 할 수 없으며, 시도 할 경우 아래와 같은 오류가 발생합니다.

scala> something = 5 * 6
<console>:8: error: value something_= is not a member of object $iw
       something = 5 * 6
       ^

클래스가 다음과 같이 정의 된 경우 :

scala> class Person(val name: String, var age: Int)
defined class Person

다음으로 인스턴스화했습니다.

scala> def personA = new Person("Tim", 25)
personA: Person

특정 Person 인스턴스 (예 : 'personA')에 대해 변경 불가능한 레이블 이 작성됩니다. 변경 가능한 필드 'age'를 수정해야 할 때마다 이러한 시도는 실패합니다.

scala> personA.age = 44
personA.age: Int = 25

예상대로 '연령'은 변경할 수없는 레이블의 일부입니다. 이 작업을 수행하는 올바른 방법은 다음 예제와 같이 변경 가능한 변수를 사용하는 것입니다.

scala> var personB = new Person("Matt", 36)
personB: Person = Person@59cd11fe

scala> personB.age = 44
personB.age: Int = 44    // value re-assigned, as expected

명확하게, 가변 변수 참조 (즉, 'personB')에서 클래스 가변 필드 'age'를 수정할 수 있습니다.

I would still stress the fact that everything comes from the above stated difference, that has to be clear in mind of any Scala programmer.


With

def person = new Person("Kumar", 12) 

you are defining a function/lazy variable which always returns a new Person instance with name "Kumar" and age 12. This is totally valid and the compiler has no reason to complain. Calling person.age will return the age of this newly created Person instance, which is always 12.

When writing

person.age = 45

you assign a new value to the age property in class Person, which is valid since age is declared as var. The compiler will complain if you try to reassign person with a new Person object like

person = new Person("Steve", 13)  // Error

To provide another perspective, "def" in Scala means something that will be evaluated each time when it's used, while val is something that is evaluated immediately and only once. Here, the expression def person = new Person("Kumar",12) entails that whenever we use "person" we will get a new Person("Kumar",12) call. Therefore it's natural that the two "person.age" are non-related.

This is the way I understand Scala(probably in a more "functional" manner). I'm not sure if

def defines a method
val defines a fixed value (which cannot be modified)
var defines a variable (which can be modified)

is really what Scala intends to mean though. I don't really like to think that way at least...


As Kintaro already says, person is a method (because of def) and always returns a new Person instance. As you found out it would work if you change the method to a var or val:

val person = new Person("Kumar",12)

Another possibility would be:

def person = new Person("Kumar",12)
val p = person
p.age=20
println(p.age)

However, person.age=20 in your code is allowed, as you get back a Person instance from the person method, and on this instance you are allowed to change the value of a var. The problem is, that after that line you have no more reference to that instance (as every call to person will produce a new instance).

This is nothing special, you would have exactly the same behavior in Java:

class Person{ 
   public int age; 
   private String name;
   public Person(String name; int age) {
      this.name = name;  
      this.age = age;
   }
   public String name(){ return name; }
}

public Person person() { 
  return new Person("Kumar", 12); 
}

person().age = 20;
System.out.println(person().age); //--> 12

Let's take this:

class Person(val name:String,var age:Int )
def person =new Person("Kumar",12)
person.age=20
println(person.age)

and rewrite it with equivalent code

class Person(val name:String,var age:Int )
def person =new Person("Kumar",12)
(new Person("Kumar", 12)).age_=(20)
println((new Person("Kumar", 12)).age)

See, def is a method. It will execute each time it is called, and each time it will return (a) new Person("Kumar", 12). And these is no error in the "assignment" because it isn't really an assignment, but just a call to the age_= method (provided by var).

참고URL : https://stackoverflow.com/questions/4437373/use-of-def-val-and-var-in-scala

반응형