一 Scala中的方法其实就是函数,声明规则请参考函数式编程中的函数声明
基本语法
def 方法名(参数列表) [:返回值类型] = {
方法体
}
class Dog {
private var sal: Double = _
var food : String = _
def cal(n1: Int, n2: Int): Int = {
return n1 + n2
}}
def main(args: Array[String]): Unit = {
val m = new MethodExec()
m.width = 2.1
m.len =2.4
println(("面积=" + m.area()))
}
}
class MethodExec{
var len = 0.0
var width = 0.0
def area(): Double = {
val str = (this.len * this.width).formatted("%.2f")
str.toDouble
}
方法的调用机制原理
1) scala开始执行时,先在栈区开辟一个main栈。main栈是最后被销毁
2) 程序在执行到一个方法时,总会开一个新的栈。
3) 每个栈是独立的空间,变量(基本数据类型)是独立的,相互不影响(引用类型除外)
4) 方法执行完毕后,该方法开辟的栈就会被jvm机回收(指针移动,引用使用不到了)
二 构造器
构造器(constructor)又叫构造方法,是类的一种特殊的方法,它的主要作用是完成对新对象的初始化
- Java中一个类可以定义多个不同的构造方法,构造方法重载
- 如没有定义构造方法,系统会自动给类生成一个默认无参构造方法(也叫默认构造器),比如 Person (){
- 一旦定义了自己的构造方法(构造器),默认的构造方法就覆盖了,就不能再使用默认的无参构造方法,除非显示的定义一下,即: Person(){};
Scala构造器的介绍
- Scala构造对象也需要调用构造方法,并且可以有任意多个构造方法(即scala中构造器也支持重载)。
- Scala类的构造器包括: 主构造器 和 辅助构造器
Scala构造器的基本语法
class 类名(形参列表) { // 主构造器 有且只有一个
// 类体
def this(形参列表) { // 辅助构造器
}
def this(形参列表) { //辅助构造器可以有多个, 通过参数来区分
}
}
object ConDemo2 {
def main(args: Array[String]): Unit = {
val b = new B()
val b_alex = new B("ALEX") // 先调 主构造器this (this is A) 再调 辅助构造器 def this (this is b)
}
}
/**输出
* this is A
* this is A
* this is B
*/
class A {
println( "this is A")
}
class B extends A{
def this(name: String){
this
println("this is B")
}
}
def main(args: Array[String]): Unit = {
val p1 = new Person2("Alex")
}
}
//定义了一个Person类 Person 有4个构造器
class Person2 private() { // private 主构造器私有,想掉对象,必须通过辅助
var name: String = _
var age: Int = _
def this(name : String) {
//辅助构造器无论是直接或间接,最终都一定要调用主构造器,执行主构造器的逻辑
//而且需要放在辅助构造器的第一行[这点和java一样,java中一个构造器要调用同类的其它构造器,也需要放在第一行]
this() //直接调用主构造器
this.name = name
}
//辅助构造器
def this(name : String, age : Int) {
this() //直接调用主构造器
this.name = name
this.age = age
}
def this(age : Int) {
this("匿名") //调用主构造器,因为 def this(name : String) 中调用了主构造器!
this.age = age
}
}
Scala构造器注意事项和细节
- Scala构造器作用是对象的初始化,构造器没有返回值,主构造器的声明直接放置于类名之后
- 主构造器会执行类定义中的所有语句,即:构造器也是方法(函数),传递参数和使用方法和前面的函数部分内容没有区别
- 如果主构造器无参数,小括号可省略,构建对象时调用的构造方法的小括号也可以省略 [ class AA{ } new AA; new AA() ]
- 辅助构造器名称为this(这个和Java是不一样的),多个辅助构造器通过不同参数列表进行区分, 在底层就是f构造器重载
- 如果想让主构造器变成私有的,可以在()之前加上private,这样用户只能通过辅助构造器来构造对象了
- 辅助构造器的声明不能和主构造器的声 明一致,会发生错误(即构造器名重复)
属性update
- 类的主构造器的形参未用任何修饰符修饰,那么这个参数是局部变量。
- 使用val关键字声明,那么参数作为类的私有的只读属性使用
- 使用var关键字声明,那么将参数作为类的成员属性使用,并会提供属性对应的xxx()[类似getter]/xxx_$eq()[类似setter]方法,即这时的成员属性是私有的,但是可读写
-
给某个属性加入@BeanPropetry注解后,会生成getXXX和setXXX的方法 并且对原来底层自动生成类似xxx(),xxx_$eq()方法,没有冲突,二者可以共存
def main(args: Array[String]): Unit = {
val Engineer = new Engineer("alex")
Engineer.name //不能访问 inName
val Engineer2 = new Engineer2("alex2")
Engineer2.inName //可以访问 inName //无法修改
val Engineer3 = new Engineer3("bob")
Engineer3.inName = "mary" // 可以修改
Engineer3.name = "sumi"
Engineer3.setName("sumi") // //使用 @BeanProperty 自动生成 getXxx 和 setXxx
}
}
class Engineer(inName: String) {
var name = inName
}
//. 如果 主构造器是Engineer2(val inName: String) ,那么 inName就是Engineer2的一个private的只读属性
class Engineer2(val inName: String) {
var name = inName
}
// 如果 主构造器是Engineer3(var inName: String) ,那么 inName就是Engineer3的一个
// 一个private 的可以读写属性
class Engineer3(var inName: String) {
@BeanProperty var name = inName
}