Controlling the Visibility of Constructor Fields

原文链接

Problem

You want to control the visibility of fields that are used as constructor parameters in a Scala class.

Solution

As shown in the following examples, the visibility of constructor fields in a Scala class is controlled by whether the fields are declared as valvar, without either val or var, and whether private is also added to the fields.

Here’s the short version of the solution:

  • If a field is declared as a var, Scala generates both getter and setter methods for that field.
  • If the field is a val, Scala generates only a getter method for it.
  • If a field doesn’t have a var or val modifier, Scala gets conservative, and doesn’t generate a getter or setter method for the field.
  • Additionally, var and val fields can be modified with the private keyword, which prevents getters and setters from being generated.

See the examples that follow for more details.

var fields

If a constructor parameter is declared as a var, the value of the field can be changed, so Scala generates both getter and setter methods for that field. In the following examples, the constructor parameter name is declared as a var, so the field can be accessed and mutated:

scala> class Person(var name: String)
defined class Person

scala> val p = new Person("Alvin Alexander")
p: Person = [email protected]

// getter
scala> p.name
res0: String = Alvin Alexander

// setter
scala> p.name = "Fred Flintstone"
p.name: String = Fred Flintstone

scala> p.name
res1: String = Fred Flintstone

As shown, Scala does not follow the JavaBean naming convention when generating accessor and mutator methods.

val fields

If a constructor field is defined as a val, the value of the field can’t be changed once it’s been set; it’s immutable (like final in Java). Therefore it makes sense that it should have an accessor method, and should not have a mutator method:

scala> class Person(val name: String)
defined class Person

scala> val p = new Person("Alvin Alexander")
p: Person = [email protected]

scala> p.name
res0: String = Alvin Alexander

scala> p.name = "Fred Flintstone"
<console>:11: error: reassignment to val
       p.name = "Fred Flintstone"
              ^

The last example fails because a mutator method is not generated for a val field.

Fields without val or var

When neither val nor var are specified on constructor parameters, the visibility of the field becomes very restricted, and Scala doesn’t generate accessor or mutator methods:

scala> class Person(name: String)
defined class Person

scala> val p = new Person("Alvin Alexander")
p: Person = [email protected]

scala> p.name
<console>:12: error: value name is not a member of Person
              p.name
                ^

Adding private to val or var

In addition to these three basic configurations, you can add the private keyword to a val or var field. This keyword prevents getter and setter methods from being generated, so the field can only be accessed from within members of the class:

scala> class Person(private var name: String) { def getName {println(name)}  }
defined class Person

scala> val p = new Person("Alvin Alexander")
p: Person = [email protected]

scala> p.name
<console>:10: error: variable name in class Person cannot be accessed in Person
              p.name
                ^

scala> p.getName
Alvin Alexander

Attempting to access p.name fails because a getter method is not generated for the name field, so callers can’t access it directly, but p.getName works because it can access the name field.

Discussion

If this is a little confusing, it helps to think about the choices the compiler has when generating code for you. When a field is defined as a val, by definition its value can’t be changed, so it makes sense to generate a getter, but no setter. By definition, the value of a var field can be changed, so generating both a getter and setter make sense for it.

The private setting on a constructor parameter gives you additional flexibility. When it’s added to a val orvar field, the getter and setter methods are generated as before, but they’re marked private. (I rarely use this feature, but it’s there if you need it.)

The accessors and mutators that are generated for you based on these settings are summarized in Table 4-1.

Table 4-1. The effect of constructor parameter settings


Visibility


Accessor?


Mutator?


var


Yes


Yes


val


Yes


No


Default visibility (no var or val)


No


No


Adding the private keyword to var or val


No


No

You can also manually add your own accessor and mutator methods. See Recipe 4.6, for more information.

Case classes

Parameters in the constructor of a case class differ from these rules in one way. Case class constructor parameters are val by default. So if you define a case class field without adding val or var, like this:

case class Person(name: String)

you can still access the field, just as if it were defined as a val:

scala> val p = Person("Dale Cooper")
p: Person = Person(Dale Cooper)

scala> p.name
res0: String = Dale Cooper

Although this is slightly different than a “regular” class, it’s a nice convenience and has to do with the way case classes are intended to be used in functional programming, i.e., as immutable records. See Recipe 4.14, for more information about how case classes work.

时间: 2024-10-27 04:21:36

Controlling the Visibility of Constructor Fields的相关文章

Hibernate 第一个Hibernate应用程序

Chapter 1. Tutorial   第一章 使用说明书 Table of Contents   目录 1.1. Part 1 - The first Hibernate Application   第一节 第一个Hibernate应用程序 1.1.1. Setup   设置开发环境 1.1.2. The first class  创建第一个类 1.1.3. The mapping file  创建类与数据库表的映射文件 1.1.4. Hibernate configuration  Hi

commons-X系列

1 commons-lang 1.1 ReflectionToStringBuilder 将对象进行字符串拼接 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding co

proguard usage

Usage To run ProGuard, just type: java -jar proguard.jar options ... You can find the ProGuard jar in the lib  directory of the ProGuard distribution. Alternatively, the bin  directory contains some short Linux and Windows scripts containing this com

[Java Basics] Stack, Heap, Constructor

Good about Java: friendly syntax, memory management[GC can collect unreferenced memory resources], object-oriented features, portability. Stack Stores method invocations, local variables(include object reference, but the object itself is still stored

JAVA进阶之旅(二)——认识Class类,反射的概念,Constructor,Fiald,Method,反射Main方法,数组的反射和实践

JAVA进阶之旅(二)--认识Class类,反射的概念,Constructor,Fiald,Method,反射Main方法,数组的反射和实践 我们继续聊JAVA,这次比较有意思,那就是反射了 一.认识Class类 想要反射,你就必须要了解一个类--Class,我们知道,java程序中的各个java类都属于同一事物,我们通常用Classliability描述对吧,反射这个概念从JDK1.2就出来了,历史算是比较悠久了,这个Class可不是关键字哦,这个是一个类,他代表的是一类事物: 我们归根结底就

关于HTML面试题汇总之visibility

一.页面可见性(visibility) 主要提供两个属性,一个事件(都在document对象上):1. 属性:   1.1.  hidden:获取或设置当前页面的可见性,boolean值:   1.2. visibilityState: 获取当前页面可见性状态,值为hidden.visibility其中一个2. 事件:visibilityChange:页面可见性发生改变时触发的事件 3. 由于各类浏览器的支持情况不一致,都需要加上私有属性的前缀,如 webkit.moz.ms.o等.在ie9-不

Virtual member call in a constructor

http://stackoverflow.com/questions/119506/virtual-member-call-in-a-constructor (Assuming you're writing in C# here) When an object written in C# is constructed, what happens is that the initializers run in order from the most derived class to the bas

System and method for controlling switching between VMM and VM using enabling value of VMM timer indicator and VMM timer value having a specified time

In one embodiment, a method includes transitioning control to a virtual machine (VM) from a virtual machine monitor (VMM), determining that a?VMM?timer indicator is set to an enabling value, and identifying a?VMM?timer?value configured by the?VMM. Th

Core Java Volume I — 4.4. Static Fields and Methods

4.4. Static Fields and MethodsIn all sample programs that you have seen, the main method is tagged with the static modifier. We are now ready to discuss the meaning of this modifier.4.4.1. Static FieldsIf you define a field as static, then there is o