Scala for the Impatients---(5)Classes
Simple Classes and Parameterless Methods
In Scala, a class is not declared as public . A Scala source file can contain multiple classes, and all of them have public visibility.
You can call a parameterless method (such as current ) with or without parentheses:
myCounter.current // OK
myCounter.current() // Also OK
You can enforce this style by declaring current without () :
class Counter {
...
def current = value // No () in definition
}
Properties with Getters and Setters
Scala provides getter and setter methods for every field.
class Person {
var age = 0//public field
}
Scala generates a class for the JVM with a private age field and getter and setter methods. These methods are public because we did not declare age as private. For a private field, the getter and setter methods are private. In Scala, the getter and setter methods are called age and age_= respectively. For example:
println(fred.age) // Calls the method fred.age()
fred.age = 21 // Calls fred.age_=(21)
java中的getter函数对应scala中的fred.age(), java中的setter函数对应scala中的fred.age_=(int).
At any time, you can redefine the getter and setter methods yourself:
class Person {
private var privateAge = 0 // Make private and rename
def age = privateAge
def age_=(newValue: Int) {
if (newValue > privateAge) privateAge = newValue; // Can’t get younger
}
}
• If the field is private, the getter and setter are private.
• If the field is a val, only a getter is generated.
• If you don’t want any getter or setter, declare the field as private[this]
Properties with Only Getters
A read-only property with a getter but no setter, then use a val field:
class Message {
val timeStamp = new java.util.Date
...
}
A property that a client can’t set at will, but that is mutated in some other way:
class Counter {
private var value = 0//private:说明getter和setter为private,客户端无法调用
def increment() { value += 1 }//只有通过此函数进行修改,类似于setter功能
def current = value // 重新定义一个函数current,替代value的getter函数。注意No () in declaration,调用的时候也不能有()
}
Object-Private Fields
n Scala (as well as in Java or C++), a method can access the private fields of all objects of its class. For example:
class Counter {
private var value = 0
def increment() { value += 1 }
def isLess(other : Counter) = value < other.value
// Can access private field of other object
}
Accessing other.value is legal because other is also a Counter object.
一种更加严格的限制就是对value变量的申明中的private后面加上[this]:
private[this] var value=0 //Accessing someObject.value is not allowed
这样只有Counter类的当前对象能够访问value,Counter类的其他对象不能,这叫做object-private。With a class-private field, Scala generates private getter and setter methods. However, for an object-private field, no getters and setters are generated at all.
The private[ ClassName ] qualifier states that only methods of the given class can access the given field. Here, the ClassName must be the name of the class being defined or an enclosing class.
Bean Properties
When you annotate a Scala field with @BeanProperty , then a pair of getFoo / setFoo methods are automatically generated. For example:
import scala.reflect.BeanProperty
class Person {
@BeanProperty var name: String = _
}
generates four methods:
1. name: String
2. name_=(newValue: String): Unit
3. getName(): String
4. setName(newValue: String): Unit
If you define a field as a primary constructor parameter, and you want JavaBeans getters and setters, annotate the constructor parameter like this:
class Person(@BeanProperty var name: String)
Auxiliary Constructors
As in Java or C++, a Scala class can have as many constructors as you like. However, a Scala class has one constructor that is more important than all the others, called the primary constructor. In addition, a class may have any number of auxiliary constructors.
1. The auxiliary constructors are called this . (In Java or C++, constructors have
the same name as the class—which is not so convenient if you rename the class.)
2. Each auxiliary constructor must start with a call to a previously defined auxiliary constructor or the primary constructor.
class Person {
private var name = ""
private var age = 0
def this(name: String) { // An auxiliary constructor
this() // Calls primary constructor
this.name = name
}
def this(name: String, age: Int) { // Another auxiliary constructor
this(name) // Calls previous auxiliary constructor
this.age = age
}
}
You can construct objects of this class in three ways:
val p1 = new Person // Primary constructor
val p2 = new Person("Fred") // First auxiliary constructor
val p3 = new Person("Fred", 42) // Second auxiliary constructor
The Primary Constructor
The primary constructor is not defined with a this method. Instead, it is interwoven with the class definition.
1. The parameters of the primary constructor are placed immediately after the
class name.
class Person(val name: String, val age: Int) {
// Parameters of primary constructor in (...)
...
}
Parameters of the primary constructor turn into fields that are initialized with the construction parameters. In our example, name and age become fields of the Person class. A constructor call such as new Person("Fred", 42) sets the name and age fields.
Half a line of Scala is the equivalent of seven lines of Java:
public class Person { // This is Java
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String name() { return this.name; }
public int age() { return this.age; }
...
}
2. The primary constructor executes all statements in the class definition. For example, in the following class:
class Person(val name: String, val age: Int) {
println("Just constructed another person")
def description = name + " is " + age + " years old"
}
The println statement is a part of the primary constructor. It is executed whenever an object is constructed.
This is useful when you need to configure a field during construction. For example:
class MyProg {//If there are no parameters after the class name, then the class has a primary constructor with no parameters.
private val props = new Properties
props.load(new FileReader("myprog.properties"))
// The statement above is a part of the primary constructor
...
}
Nested Classes
In Scala, you can nest just about anything inside anything. You can define functions inside other functions, and classes inside other classes. For example:
import scala.collection.mutable.ArrayBuffer
class Network {
class Member(val name: String) {
val contacts = new ArrayBuffer[Member]
}
private val members = new ArrayBuffer[Member]
def join(name: String) = {
val m = new Member(name)
members += m
m
}
}
make a new inner object: new chatter.Member
posted on 2016-04-20 00:15 chaseblack 阅读(169) 评论(0) 编辑 收藏 举报