1) Java时面向对象的编程语言,因为历史缘由,Java中海存在着非面向对象的内容:基本类型,null,静态方法等java
2) Scala语言来自于Java,因此天生就是面向对象的语言,并且Scala时纯粹的面相对象的语言,即在Scala中,一切皆为对象程序员
3) 在面向对象的学习过程当中能够对比着Java语言学习面试
1) 类是抽象的,概念的表明一类事物,好比人类,猫类...编程
2) 对象是具体的,实际的,表明一个具体事物框架
3) 类是对象的模版,对象是类的一个个体,对应一个实例编程语言
4) Scala中类和对象的区别和联系和Java是同样的ide
-基本语法函数式编程
[修饰符] class 类名 {函数
类体工具
}
-定义类的注意事项
1) Scala语法中,类并不声明为public,全部这些类都具备公有可见性(默认就是public)
2) 一个Scala源文件能够包含多个类,并且默认都是public
-基本介绍
属性是类的一个组成部分,通常是值数据类型,也但是引用类型
-案例演示
class Dog { var name = "Tom" var lover = new Fish } class Fish { }
-注意事项和细节说明
1) 属性的定义语法同变量,示例:[访问修饰符] var 属性名称 [: 类型] = 属性值
2) 属性的定义类型能够为任意类型,包含值类型或引用类型
3) Scala中声明一个属性,必须显示的初始化,而后根据初始化数据的类型自动推断,属性类型能够省略(这点和Java不一样)
4) 若是赋值为null,则必定要加类型,由于不加类型,那么该属性的类型就是Null类型
5) 若是在定义属性时,暂时不赋值,也可使用符号_(下划线),让系统分配默认值
class A { var a1: String = _ //null var a2: Byte = _ // 0 var a3: Double = _ // 0.0 var a4: Boolean = _ // false }
说明:属性的高级部分和构造器(构造方法/函数)相关,具体介绍将在构造器部分详解
-基本语法
val | var 对象名 [: 类型] = new 类型()
-说明
1) 若是咱们不但愿改变对象的引用(即:内存地址),应该声明为val性质的,不然声明为var,Scala设计者推荐使用val,由于通常来讲,在程序中,咱们只是改变对象属性的值,而不是改变对象的引用
2) Scala在声明对象变量时,能够根据建立对象的类型自动推断,因此类型声明能够省略,但当类型和后面new对象类型有继承关系时即多态,就必须写了
3) 案例演示
object boke_demo01 { def main(args: Array[String]): Unit = { val emp = new Emp // emp 类型就是Emp //若是咱们但愿将子类对象,交给父类的引用,这时就须要写上类型 val emp2: Person = new Emp } } class Person { } class Emp extends Person { }
-案例演示
object boke_demo01 { def main(args: Array[String]): Unit = { val p1 = new Person2 p1.name = "jack" p1.age = 10 val p2 = p1 println(p1 == p2) // true p1.name = "tom" println("p2.name=" + p2.name) // p2.name=tom } } class Person2 { var name = "" var age: Int = _ //若是是用 _ 方式给默认值,则属性必须指定类型 }
-案例演示对应的内存布局图
Scala中的方法其实就是函数,声明规则请参考函数式编程中的函数声明
def 方法名[: 返回值类型] = {
方法体
}
给Cat类添加cal方法,能够计算两个数的和
object MethodDemo01 { def main(args: Array[String]): Unit = { val cat = new Cat println(cat.cal(10, 20)) } } class Cat { private var sal: Double = _ var food: String = _ //方法 def cal(n1: Int, n2: Int): Int = { return n1 + n2 } }
咱们来看一个需求:前面咱们在建立Person的对象时,是先把一个对象建立好后,再给他的姓名和年龄属性赋值,若是如今要求,在建立Person类对象时,就直接制定这个对象的姓名和年龄,该怎么作?这时就可使用构造方法/构造器
[修饰符] 方法名 (参数列表) {
构造方法体
}
1) 在Java中一个类能够定义多个不一样的构造方法,构造方法重载
2) 若是程序员没有定义构造方法,系统会自动给类生成一个无参构造方法(也叫默认构造器),好比:Person(){}
3) 一旦定义了本身的构造方法(构造器),默认的构造方法就覆盖了,就不能使用默认的无参构造方法,除非显示的定义一下,即:Person(){}
在前面定义的Person类中添加两个构造器
第一个无参构造器:利用构造器设置全部人的age属性初始值都为18
第二个带name和age两个参数的构造器:使得每次建立Person对象的同时初始化对象的name属性值和age属性值
public class Person { public String name; public int age; public String getInfo() { return name + "\t" + age; } public Person() { age = 18; } public Person(String name, int age) { this.name = name; this.age = age; } }
和Java同样,Scala构造对象也须要调用构造方法,而且能够有任意多个构造方法(即Scala中构造器也支持重载),Scala类的构造器包括:主构造器和辅助构造器
class 类名(形参列表) { //主构造器
def this(形参列表){ //辅助构造器
}
def this(形参列表){ //辅助构造器能够有多个...
}
}
辅助构造器的函数名this,能够有多个,编译器经过不一样参数来区分
建立Person对象的同时初始化对象的name属性和age属性,案例演示
object boke_demo01 { def main(args: Array[String]): Unit = { // val p1 = new Person("Jack", 20) // println(p1) //下面这句话就会调用def this(name:String) val p2 = new Person("Tom") println(p2) } } //构造器的快速入门 //建立Person对象的同时初始化对象的age属性值和name属性值 class Person(inName: String, inAge: Int) { var name: String = inName var age: Int = inAge age += 10 println("~~~~~~~~~~") //重写了toString,便于输出对象的信息 override def toString: String = { "name=" + this.name + "\t age" + this.age } println("ok~~~~~") println("age=" + age) def this(name: String) { //辅助构造器,必须在第一行显式调用主构造器(能够是直接,也能够是间接) this("Jack", 10) //this this.name = name //从新赋值 } }
1) Scala构造器的做用是完成对新对象的初始化,构造器没有返回值
2) 主构造器的声明直接放置于类名以后
3) 主构造器会执行类定义中的全部语句,这里能够体会到Scala的函数式编程和面向对象编程融合在一块儿,即:构造器也是方法(函数),传递参数和使用方法和前面的函数部份内容没有区别
4) 若是主构造器没有参数,小括号能够省略,构建对象时调用的构造方法的小括号也能够省略
class AA { } val a = new AA val b = new AA()
5) 辅助构造器名称为this(这个和Java是不同的),多个辅助构造器经过不一样参数列表进行区分,在底层就是构造器重载
object boke_demo01 { def main(args: Array[String]): Unit = { val p1 = new Person2("jack") p1.showInfo() } } //定义了一个Person类 //Person 有几个构造器 4 class Person2 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 } def showInfo(): Unit = { println("person信息以下:") println("name=" + this.name) println("age=" + this.age) } }
6) 若是想要主构造器编程私有的,能够在()以前加上private,这样用户只能经过辅助构造器来构造对象了,好比: class Person2 private(){}
7) 辅助构造器的声明不能和主构造器的声明一致,会发生错误(即构造器名重复)
对属性的内容作一个增强
1) Scala类的主构造器的形参未用任何修饰符修饰,那么这个参数是局部变量
2) 若是参数使用val关键字声明,那么Scala会将参数做为类的私有只读属性使用
3) 若是参数使用var关键字声明,那么Scala会将参数做为类的成员属性使用,并会提供对应的xxx()[相似getter]/xxx_$eq()[相似setter]方法,即这时的成员属性是私有的,可是可读写
4) 案例演示
object boke_demo01 { def main(args: Array[String]): Unit = { val worker = new Worker("smith") worker.name //不能访问 inName val worker2 = new Worker2("smith2") worker2.inName //能够访问 inName println("hello!") val worker3 = new Worker3("jack") worker3.inName = "mary" println(worker3.inName) } } //若是 主构造器是Worker(inName: String) ,那么 inName就是一个局部变量 class Worker(inName: String) { var name = inName } //若是 主构造器是Worker2(val inName: String) ,那么 inName就是Worker2的一个private的只读属性 class Worker2(val inName: String) { var name = inName } // 若是 主构造器是Worker3(var inName: String) ,那么 inName就是Worker3的一个 // 一个private 的能够读写属性 class Worker3(var inName: String) { var name = inName }
JavaBean规范定义了Java的属性是像getXxx()和setXxx()方法。许多Java工具(框架)都依赖这个命名习惯。为了Java的互操做性。将Scala字段加@BeanProperty时,这样会自动生成规范的setXxx/getXxx方法。这时可使用 对象.setXxx()和 对象.getXxx()来调用属性
注意:给某个属性加入@BeanPropetry注解后,会生成getXxx和setXxx的方法,而且对原来底层自动生成相似xxx(),xxx_$eq()方法,没有冲突,两者能够共存
import scala.beans.BeanProperty object boke_demo01 { def main(args: Array[String]): Unit = { val car = new Car car.name = "宝马" println(car.name) //使用 @BeanProperty 自动生成 getXxx 和 setXxx car.setName("奔驰") println(car.getName()) } } class Car { @BeanProperty var name: String = null }
class Person { var age: Short = 90 var name: String = _ def this(n: String, a: Int) { this() this.name = n this.age = a } } var p: Person = new Person ("小倩", 20)
1) 加载类的信息(属性信息,方法信息)
2) 在内存中(堆)开辟空间
3) 使用父类的构造器(主和辅助)进行初始化
4) 使用主构造器对属性进行初始化[age:90, name:null]
5) 使用辅助构造器对属性进行初始化[age:20, name:小倩]
6) 将开辟的对象的地址赋给p这个引用