1. 面向对象编程(上)
定义类
[修饰符] class 类名 {
类体
}
- scala语法中,类并不声明为public,所有这些类都具有公有可见性(即默认就是public),[修饰符在后面再详解].
- 一个Scala源文件可以包含多个类, 每个类默认都是public
- 如果我们不希望改变对象的引用(即:内存地址), 应该声明为val 性质的,否则声明为var, scala设计者推荐使用val ,因为一般来说,在程序中,我们只是改变对象属性的值,而不是改变对象的引用。
- scala在声明对象变量时,可以根据创建对象的类型自动推断,所以类型声明可以省略,但当类型和后面new 对象类型有继承关系即多态时,就必须写了
object Test{
def main(args: Array[String]): Unit = {
val cat = new Cat
cat.name = "小白"
cat.age = 3
cat.color = "白色"
}
}
class Cat {
var name: String = _
var age = 0
var color: String = ""
}
构造器
class 类名(形参列表) { // 主构造器 类名定义
// 类体
def this(形参列表) { // 辅助构造器
}
def this(形参列表) { //辅助构造器可以有多个...
}
}
- Scala构造器作用是完成对新对象的初始化,构造器没有返回值。
- 主构造器的声明直接放置于类名之后
- 主构造器会执行类定义中的所有语句
- 如果主构造器无参数,小括号可省略,构建对象时调用的构造方法的小括号也可以省略
- 辅助构造器名称为this(这个和Java是不一样的),多个辅助构造器通过不同参数列表进行区分, 在底层就是构造器重载,辅助构造器无论是直接或间接,最终都一定要调用主构造器,执行主构造器的逻辑, 而且调用主构造器语句一定要放在辅助构造器的第一行
- 如果想让主构造器变成私有的,可以在()之前加上private,这样用户不能直接通过主构造器来构造对象
object Test{
def main(args: Array[String]): Unit = {
val person = new Person
person.showInfo()
val person1 = new Person("zs", 12)
person1.showInfo()
val person2 = new Person("zs")
person2.showInfo()
val person3 = new Person(24, "zs")
person3.showInfo()
//class私有 val cat: Cat = new Cat//主构造器调用报错(无参)
val cat: Cat = new Cat("kk", 1)
cat.showInfo()
// val og: Dog = new Dog("nn")//直接调用主构造函数报错
val dog: Dog = new Dog("nn", 10)
dog.showInfo()
}
}
class Person { // 会生成一个默认的无参构造器
var name: String = _
var age: Int = _
println("主构造器会执行类定义中的所有语句") //由于上面创建了4个对象,会被打印4次
def this(name: String, age: Int) {
this
// this.name = name
// this.age = age
}
def this(name: String) {
//所有的辅助构造器必须调用主构造器 => 为了底层能够实现对父类的初始化
this()
println(name)
this.name = name
}
def this(age: Int, name: String) {
this
this.name = name
this.age = age
}
def showInfo(): Unit = {
println("person信息如下:")
println("name=" + this.name)
println("age=" + this.age)
}
}
class Cat private() { //主构造函数无参
var name: String = _
var age: Int = _
def this(name: String, age: Int) {
this()
this.name = name
this.age = age
}
def showInfo(): Unit = {
println("cat:")
println("name=" + this.name)
println("age=" + this.age)
}
}
class Dog private(dName: String) {//主构造函数含参 dName
var name: String = dName
var age: Int = _
def this(name: String, age: Int) {
this(name)
this.age = age
}
def showInfo(): Unit = {
println("dog:")
println("name=" + this.name)
println("age=" + this.age)
}
}
输出结果:
主构造器会执行类定义中的所有语句
person信息如下:
name=null
age=0
主构造器会执行类定义中的所有语句
person信息如下:
name=null
age=0
主构造器会执行类定义中的所有语句
zs
person信息如下:
name=zs
age=0
主构造器会执行类定义中的所有语句
person信息如下:
name=zs
age=24
cat:
name=kk
age=1
dog:
name=nn
age=10
bean属性
- 给某个属性加入@BeanPropetry注解后,会生成getXXX和setXXX的方法
- 并且对原来底层自动生成类似xxx(),xxx_$eq()方法,没有冲突,二者可以共存。
object Test{
def main(args: Array[String]): Unit = {
val car = new Car
car.name = ""
car.setName("Mercedes")
car.setColor("black")
printf("carName:%s\n", car.getName)
printf("carColor:%s", car.getColor)
}
class Car {
//默认生成 public name() 和 public name_$eq
//如果加入了@BeanProperty 注解,就会再生成 public getName() 和 public setName()
@BeanProperty
var name: String = _
@BeanProperty
var color: String = _
}
}
输出结果:
carName:Mercedes
carColor:black
Scala对象创建对象流程
object Test{
def main(args: Array[String]): Unit = {
var p: Person = new Person("小倩", 20)
}
}
class Person {
var age: Int = 90
var name: String = _
def this(n: String, a: Short) {
this()
this.name = n
this.age = a
}
}
- 加载类的信息(属性信息和方法信息)
- 在内存中(堆)给对象开辟空间
- 使用父类的构造器(主构造器/辅助构造器)完成父类的初始化 (多个父类)
- 使用本类的主构造器完成初始化( age = 90 name = “null”)
- 使用本类的辅助构造器继续初始化(age =20,name = “小倩”)
- 将对象在内存中的地址赋给 p 这个引用