五、Scala面向对象编程(基础)

我会带着你远行 2024-04-17 05:42 133阅读 0赞

目录

一、类与对象

1、Scala语言是面向对象的

2、类和对象的区别和联系

3、定义类

4、创建对象

5、属性

6、方法

7、构造器

8、对象创建的流程分析


一、类与对象

1、Scala语言是面向对象的

  • Java是面向对象的编程语言,由于历史原因,Java中还存在着非面向对象的内容:基本类型 ,null,静态方法等。
  • Scala语言来自于Java,所以天生就是面向对象的语言,而且Scala是纯粹的面向对象的语言,即在Scala中,一切皆为对象。

2、类和对象的区别和联系

  • 类是抽象的,概念的,代表一类事物,比如人类,猫类..
  • 对象是具体的,实际的,代表一个具体事物
  • 类是对象的模板,对象是类的一个个体,对应一个实例
  • Scala中类和对象的区别和联系 和 Java是一样的。

3、定义类

(1)基本语法

  1. [修饰符] class 类名 {
  2. 类体
  3. }

(2)定义类的注意事项

scala语法中,类并不声明为public,所有这些类都具有公有可见性(即默认就是public),[修饰符在后面再详解].
一个Scala源文件可以包含多个类.

4、创建对象

(1)基本语法

  1. val | var 对象名 [:类型] = new 类型()

(2)说明

  • 如果我们不希望改变对象的引用(即:内存地址), 应该声明为val 性质的,否则声明为var, scala设计者推荐使用val ,因为一般来说,在程序中,我们只是改变对象属性的值,而不是改变对象的引用。
  • scala在声明对象变量时,可以根据创建对象的类型自动推断,所以类型声明可以省略,但当类型和后面new 对象类型有继承关系即多态时,就必须写了

5、属性

属性是类的一个组成部分,一般是值数据类型,也可是引用类型。

(1)注意事项和细节说明

  • 属性的定义语法同变量,示例:[访问修饰符] var 属性名称 [:类型] = 属性值
  • 属性的定义类型可以为任意类型,包含值类型或引用类型
  • Scala中声明一个属性,必须显示的初始化,然后根据初始化数据的类型自动推断,属性类型可以省略(这点和Java不同)。
  • 如果赋值为null,则一定要加类型,因为不加类型, 那么该属性的类型就是Null类型.
  • 如果在定义属性时,暂时不赋值,也可以使用符号_(下划线),让系统分配默认值.
  • 不同对象的属性是独立,互不影响,一个对象对属性的更改,不影响另外一个。























类型

_ 对应的值

Byte Short Int Long

0

Float Double

0.0

String  引用类型

null

Boolean 

false

  1. class Person {
  2. var age : Int = 10
  3. var sal = 8090.9//给属性赋初值,省略类型,会自动推导
  4. var Name = null// Name 是什么类型?
  5. var address : String = null // address 是什么类型?
  6. var height :Int = _
  7. }

(2)如何访问属性

  1. 对象名.属性名

(3)、属性的高级部分

属性的高级部分和构造器(构造方法/函数) 相关

a、构造器参数

  • Scala类的主构造器的形参未用任何修饰符修饰,那么这个参数是局部变量
  • 如果参数使用val关键字声明,那么Scala会将参数作为类的私有的只读属性使用
  • 如果参数使用var关键字声明,那么那么Scala会将参数作为类的成员属性使用,并会提供属性对应的xxx()[类似getter]/xxx_$eq()[类似setter]方法,即这时的成员属性是私有的,但是可读写。

    object ClassTest {
    def main(args: Array[String]): Unit = {

    1. val person = new Person("jack")//不能访问inName
    2. val animal = new Animal("dog")//name 和inName都可访问

    // animal.inName = “”//error 不可修改inName值

    1. val machine = new Machine("bike")
    2. machine.inName = "tt"//可以修改inName值

    }
    }
    //Scala类的主构造器的形参未用任何修饰符修饰,那么这个参数是局部变量
    class Person(inName:String) {
    var name: String = inName
    }
    //如果参数使用val关键字声明,那么Scala会将参数作为类的私有的只读属性使用
    class Animal(val inName:String){
    var name: String = inName
    }
    class Machine(var inName:String){
    var name: String = inName
    }

b、Bean属性

  • JavaBeans规范定义了Java的属性是像getXxx()和setXxx()的方法。许多Java工具(框架)都依赖这个命名习惯。为了Java的互操作性。将Scala字段加@BeanProperty时,这样会自动生成规范的 setXxx/getXxx 方法。这时可以使用 对象.setXxx() 和 对象.getXxx() 来调用属性。
  • 注意:给某个属性加入@BeanPropetry注解后,会生成getXXX和setXXX的方法并且对原来底层自动生成类似xxx(),xxx_$eq()方法,没有冲突,二者可以共存。

    object ClassTest {
    def main(args: Array[String]): Unit = {

    1. val car = new Car
    2. car.setName("Jeep")
    3. println(car.getName)

    }
    }
    import scala.beans.BeanProperty
    class Car {
    @BeanProperty var name: String = null
    }

6、方法

Scala中的方法其实就是函数,声明规则请参考函数式编程中的函数声明。

(1)基本语法

  1. def 方法名(参数列表) [:返回值类型] = {
  2. 方法体
  3. }

(2)方法的调用机制原理

  • 当我们scala开始执行时,先在栈区开辟一个main栈。main栈是最后被销毁
  • 当scala程序在执行到一个方法时,总会开一个新的栈。
  • 每个栈是独立的空间,变量(基本数据类型)是独立的,相互不影响(引用类型除外)
  • 当方法执行完毕后,该方法开辟的栈就会被jvm机回收。

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3MyOTQ4NzgzMDQ_size_16_color_FFFFFF_t_70

7、构造器

构造器(constructor)又叫构造方法,是类的一种特殊的方法,它的主要作用是完成对新对象的初始化。

(1)Java构造器的特点

  • 在Java中一个类可以定义多个不同的构造方法,构造方法重载
  • 如果程序员没有定义构造方法,系统会自动给类生成一个默认无参构造方法(也叫默认构造器),比如 Person (){}
  • 一旦定义了自己的构造方法(构造器),默认的构造方法就覆盖了,就不能再使用默认的无参构造方法,除非显示的定义一下,即: Person(){};

    class Person{
    public String name;
    public int age;
    public Person(){

    1. age = 18;

    }
    public Person(String name,int age){

    1. this.name = name;
    2. this.age = age;

    }
    public String getInfo(){

    1. return name+"\t"+age;

    }
    }

(2)Scala构造器的介绍

  • 和Java一样,Scala构造对象也需要调用构造方法,并且可以有任意多个构造方法(即scala中构造器也支持重载)。
  • Scala类的构造器包括: 主构造器 和 辅助构造器
  • Scala构造器的基本语法

    //1. 辅助构造器 函数的名称this, 可以有多个,编译器通过不同参数来区分.
    class 类名(形参列表) { // 主构造器
    // 类体
    def this(形参列表) { // 辅助构造器
    }
    def this(形参列表) { //辅助构造器可以有多个…
    }
    }

    //构造器测试
    class Person(inName:String, inAge:Int){
    var name:String = inName
    var age :Int = inAge
    override def toString:String = {

    1. s"name = ${this.name} , age = ${this.age}"

    }
    }

(3)Scala构造器注意事项和细节

  • Scala构造器作用是完成对新对象的初始化,构造器没有返回值。
  • 主构造器的声明直接放置于类名之后
  • 主构造器会执行类定义中的所有语句,这里可以体会到Scala的函数式编程和面向对象编程融合在一起,即:构造器也是方法(函数),传递参数和使用方法和前面的函数部分内容没有区别,如下所示

    //构造器测试
    class Person(inName:String, inAge:Int){
    var name:String = inName
    var age :Int = inAge
    age += 10
    println(“主构造器会执行类定义中的所有语句_1”)
    override def toString:String = {

    1. s"name = ${this.name} , age = ${this.age}"

    }
    println(“主构造器会执行类定义中的所有语句_2”)
    }

  • 如果主构造器无参数,小括号可省略,构建对象时调用的构造方法的小括号也可以省略

  • 辅助构造器名称为this(这个和Java是不一样的),多个辅助构造器通过不同参数列表进行区分, 在底层就是 f 构造器重载。

    //构造器测试
    class Person() {
    var name: String =
    var age: Int =

    def this(name : String) {

    1. //辅助构造器无论是直接或间接,最终都一定要调用主构造器,执行主构造器的逻辑
    2. //而且需要放在辅助构造器的第一行[这点和java一样,java中一个构造器要调用同类的其它构造器,也需要放在第一行]
    3. this() //直接调用主构造器
    4. this.name = name

    }
    def this(name : String, age : Int) {

    1. this() //直接调用主构造器
    2. this.name = name
    3. this.age = age

    }
    def this(age : Int) {

    1. //间接调用主构造器,实际上是取调用辅助构造器def this(name : String)
    2. // 因为 def this(name : String) 中调用了主构造器!
    3. this("匿名")
    4. this.age = age

    }
    def showInfo(): Unit = {

    1. println("person信息如下:")
    2. println("name=" + this.name)
    3. println("age=" + this.age)

    }
    override def toString:String = {

    1. s"name = ${this.name} , age = ${this.age}"

    }
    }

  • 如果想让主构造器变成私有的,可以在()之前加上private,这样用户只能通过辅助构造器来构造对象了

    class Person private () {
    var name: String =
    var age: Int =

    private def this(name : String) {

    1. this()
    2. this.name = name

    }
    def this(name : String, age : Int) {

    1. this() //直接调用主构造器
    2. this.name = name
    3. this.age = age

    }
    override def toString:String = {

    1. s"name = ${this.name} , age = ${this.age}"

    }
    }

  • 辅助构造器的声明不能和主构造器的声 明一致,会发生错误(即构造器名重复)

  • 在辅助构造器中必须先调用 this 执行类的主构造器,原因如下

    object ClassTest2 {
    def main(args: Array[String]): Unit = {
    // 按照A的主构造器实例化一个对象a,在过程中会取调用父类B的主构造器

    1. val a = new A

    // 按照A的辅构造器实例化一个对象a2,在辅构造器中先调用A的主构造器时会仔调用B的主构造器
    // 来保证A和B类的继承关系,这就是为什么在辅构造器中先调用类的主构造器的原因

    1. val a2 = new A("jack")

    }
    }
    class A extends B{
    def this(name:String){

    1. this//调用A的主构造器
    2. println("this is constructor of A")

    }
    }
    class B {
    println(“B····”)
    }

8、对象创建的流程分析

  1. class Person {
  2. var age: Short = 90
  3. var name: String = _
  4. def this(n: String, a: Short) {
  5. this()
  6. this.name = n
  7. this.age =a
  8. }
  9. }

var p : Person = new Person(“小倩”,20)

流程分析

  • 加载类的信息(属性信息,方法信息)
  • 在内存中(堆)开辟空间
  • 使用父类的构造器(主和辅助)进行初始
  • 使用主构造器对属性进行初始化 【age:90, naem nul】
  • 使用辅助构造器对属性进行初始化 【 age:20, naem 小倩 】
  • 将开辟的对象的地址赋给 p这个引用

发表评论

表情:
评论列表 (有 0 条评论,133人围观)

还没有评论,来说两句吧...

相关阅读