parametry konstruktora klasy scala
Jaka jest różnica między:
class Person(name: String, age: Int) {
def say = "My name is " + name + ", age " + age
}
I
class Person(val name: String, val age: Int) {
def say = "My name is " + name + ", age " + age
}
Czy mogę zadeklarować parametry jako var
s, a później zmienić ich wartości? Na przykład,
class Person(var name: String, var age: Int) {
age = happyBirthday(5)
def happyBirthday(n: Int) {
println("happy " + n + " birthday")
n
}
}
6 answers
W pierwszej części odpowiedź brzmi:
scala> class Person(name: String, age: Int) {
| def say = "My name is " + name + ", age " + age
| }
scala> val x = new Person("Hitman", 40)
scala> x.name
<console>:10: error: value name is not a member of Person
x.name
Jeśli prefiks parametrów z val
, var
będą widoczne spoza klasy, w przeciwnym razie będą prywatne, jak widać w kodzie powyżej.
I tak, możesz zmienić wartość var, tak jak zwykle.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-26 14:08:58
To
class Person(val name: String, val age: Int)
Udostępnia pola zewnętrznie użytkownikom klasy, np. można później zrobić
val p = new Person("Bob", 23)
val n = p.name
Jeśli podasz args jako var
, to zakres jest taki sam jak dla val
, ale pola są zmienne.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-26 14:08:32
Jeśli znasz Javę, możesz uzyskać pomysł z tego przykładu:
class Person(name: String, age: Int)
Jest podobny do
class Person {
public Person(String name, int age) {
}
}
While
class Person(var name: String, var age: Int) // also we can use 'val'
Jest podobny do
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
Intuicja jest taka, że bez var/val zmienna jest dostępna tylko wewnątrz konstruktora. Jeśli zostanie dodany var/val, klasa będzie miała zmienne członkowskie o tej samej nazwie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-23 22:39:33
Odpowiedzi tutaj są naprawdę dobre, jednak zajmuję się tym, badając kod bajtowy. Gdy zastosujesz javap
do klasy, wyświetla ona pola package, protected i public oraz metody przekazywanych klas. Stworzyłem osobę z klasą.scala i wypełnił go poniższym kodem.
class Person(name: String, age: Int) {
def say = "My name is " + name + ", age " + age
}
class PersonVal(val name: String, val age: Int) {
def say = "My name is " + name + ", age " + age
}
class PersonVar(var name: String, var age: Int) {
age = happyBirthday(5)
def happyBirthday(n: Int) = {
println("happy " + n + " birthday")
n
}
}
Po skompilowaniu kodu z scalac Person.scala
generuje on trzy pliki o nazwach Person.class, PersonVal.calass , PersonVar.cass
. Uruchamiając javap
dla każdego z tych plików klas możemy zobaczyć jak struktura be:
>>javap Person.class
Compiled from "Person.scala"
public class Person {
public java.lang.String say();
public Person(java.lang.String, int);
}
W tym przypadku nie tworzy żadnej klasy variable for Person, ponieważ nie jest zadeklarowana ani przez val, ani przez val, więc nazwa i wiek mogą być użyte wewnątrz konstruktora.
>>javap PersonVal.class
public class PersonVal {
public java.lang.String name();
public int age();
public java.lang.String say();
public PersonVal(java.lang.String, int);
}
W tym przypadku ma on trzy elementy: dwa dla konstruktora wejściowego i jeden dla elementu zadeklarowanego wewnątrz constructore. Jednak nie mamy żadnego settera dla konstruktorów wejściowych, więc nie możemy zmienić wartości.
>>javap PersonVar.class
public class PersonVar {
public java.lang.String name();
public void name_$eq(java.lang.String);
public int age();
public void age_$eq(int);
public int happyBirthday(int);
public PersonVar(java.lang.String, int);
}
To to samo co przykład PersonVal, ale możemy zmienić wartości w tym przypadku za pomocą metod variable_$eq
. to nic tylko skrócona wersja variable =
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-16 15:54:20
Możesz użyć case class
i w takim przypadku klasa Person
będzie miała te zmienne dostępne poza klasą.
case class Person(name: String, age: Int)
. Następnie poniższy kod będzie działał zgodnie z oczekiwaniami. val z = new Person("John", 20); z.name //John
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-12 19:02:07
Odpowiedź @Reza, gdzie autor bada kod bajtowy za pomocą javap, pomogła mi wyjaśnić tę koncepcję najlepiej. Aby przytoczyć bardzo konkretny przykład tego przypadku, zapoznaj się z poniższym scenariuszem, który napotkałem w mojej aplikacji internetowej produkcji (Play + Scala): Jak wprowadzić parametry do metody class / trait w Scali
If I don ' t use val prefix to injected parameter authorizationHandler
then
kompilator wyrzuca ten błąd:
class MyController needs to be abstract, since method authorizationHandler in trait AuthorizationCheck of type => controllers.authapi.AuthorizationHandler is not defined
[error] class MyController @Inject() (authorizationHandler: AuthorizationHandler) extends Controller with AuthorizationCheck {
[error] ^
[error] one error found
Niestety błąd nie pomógł mi wskazać poprawnego problem, który należy przedrostkiem val
.
class MyController @Inject()(val authorizationHandler: AuthorizationHandler) extends Controller with AuthorizationCheck {
def myAction = AuthenticatedAction { implicit request =>
...
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-02 07:12:40