zoukankan      html  css  js  c++  java
  • Scala-面向对象基础

    面向对象基础

    1、定义类的基本语法

    [修饰符] class 类名 {
      类体
    }
    

    注意事项:

    1)scala语法中,类并不声明为public,所有这些类都具有公有可见性(即默认就是public)

    2)一个Scala源文件可以包含多个类

    类和对象的区别:

    1)类是抽象的,概念的,代表一类事物,比如人类,猫类..

    2)对象是具体的,实际的,代表一个具体事物

    3)类是对象的模板,对象是类的一个个体,对应一个实例

    4)Scala中类和对象的区别和联系和Java是一样的。

    2、类与对象

    1、属性

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

    1)属性的定义语法同变量,示例:

    [访问修饰符]  var 属性名称 [:类型] = 属性值
    

    2)属性的定义类型可以为任意类型,包含值类型或引用类型

    3)Scala中声明一个属性,必须显示的初始化,然后根据初始化数据的类型自动推断,属性类型可以省略(这点和Java不同)。

    4)如果赋值为null,则一定要加类型,因为不加类型, 那么该属性的类型就是Null类型;

    5)如果在定义属性时,暂时不赋值,也可以使用符号"_"(下划线),让系统分配默认值;

    类型 下划线对应的值
    Byte、Short、Int、Long 0
    Float、Double 0.0
    String和引用类型 null
    Boolean false

    6)不同对象的属性是独立,互不影响,一个对象对属性的更改,不影响另外一个。

    2、创建对象

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

    1)如果我们不希望改变对象的引用(即:内存地址), 应该声明为val性质的,否则声明为var, scala设计者推荐使用val ,因为一般来说,在程序中,我们只是改变对象属性的值,而不是改变对象的引用;

    2)scala在声明对象变量时,可以根据创建对象的类型自动推断,所以类型声明可以省略,但当类型和后面new对象类型有继承关系即多态时(比如,将子类对象交给父类引用),就必须写类型声明了

      def main(args: Array[String]): Unit = {
        val persion = new Persion;
        val emp = new Emp
        val emp2:Persion = new Emp
      }
    class Persion{
    }
    class Emp extends Persion{
    }
    

    3、方法

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

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

    方法的调用机制:

    1. 当我们scala开始执行时,先在栈区开辟一个main栈。main栈是最后被销毁

    2. 当scala程序在执行到一个方法时,总会开一个新的栈。

    3. 每个栈是独立的空间,变量(基本数据类型)是独立的,相互不影响(引用类型除外)

    4. 当方法执行完毕后,该方法开辟的栈就会被jvm机回收。

    4、构造器

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

    Scala构造对象也需要调用构造方法,并且可以有任意多个构造方法(即scala中构造器也支持重载)。

    Scala类的构造器包括: 主构造器和辅助构造器

    语法

    class 类名(形参列表) {  //主构造器
       //类体
       def  this(形参列表) {  //辅助构造器
       }
       def  this(形参列表) {  //辅助构造器可以有多个...
       }
    } 
    

    辅助构造器函数的名称为this, 可以有多个,编译器通过不同参数来区分。

    def main(args: Array[String]): Unit = {
    
        val p1 = new Person("jack",10)
        println(p1)
    
        /**
         * public static String valueOf(Object obj) {
         * return (obj == null) ? "null" : obj.toString();
         * }
         *
         * 从println方法的底层调用可以看出,打印输出的是这个传入的参数的,调用toString方法的内容
         */
    
        val p2 = new Person("tom")
        println(p2)
      }
    }
    
    class Person(inName:String,inAge:Int){
    
      var name:String = inName
      var age:Int = inAge
    
      age += 10
    
      println("----------------------")
    
      override def toString: String = {
    
        "name:"+this.name + "	 age:" + this.age
      }
    
      println("ok!!!!")
      println("age="+age)
    
      /**
       * 辅助构造器
       * 辅助构造器,必须在第一行显式调用主构造器,(可以是直接,也可以是间接)
       * @param name
       */
      def this(name:String){
    
        this("jack",10)
    
        this.name = name
      }
    

    输出结果:

    ----------------------
    ok!!!!
    age=20
    name:jack	 age:20
    ----------------------
    ok!!!!
    age=20
    name:tom	 age:20
    

    Scala构造器注意事项和细节

    1)Scala构造器作用是完成对新对象的初始化,构造器没有返回值;

    2)主构造器的声明直接放置于类名之后;

    3)主构造器会执行类定义中的所有语句,这里可以体会到Scala的函数式编程和面向对象编程融合在一起;即:构造器也是方法(函数),传递参数和使用方法和前面的函数部分内容没有区别;

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

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

    class Person2(){
    
      var name:String = _
      var age:Int = _
    
      def this(name:String){
        this()
        this.name = name
      }
    
      def this(name:String,age:Int){
        this
        this.name = name
        this.age = age
      }
    
      def this(age:Int){
        this("fym")   //def this(name:String)构造器调用了主构造器,所以相当于这里间接调用了主构造器
        this.age = age
      }
    }
    

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

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

    3、属性高级

    1、构造器参数

    1)Scala类的主构造器的形参未用任何修饰符修饰,那么这个参数是局部变量。

    2)如果主构造器的参数使用val关键字声明,那么Scala会将参数作为类的私有的只读属性使用

    3)如果主构造器的参数使用var关键字声明,那么那么Scala会将参数作为类的成员属性使用,并会提供属性对应的xxx()[类似getter]/xxx_$eq()[类似setter]方法,即这时的成员属性是私有的,但是可读写。

    2、Bean属性

    JavaBeans规范定义了Java的属性是像getXxx()和setXxx()的方法。许多Java工具(框架)都依赖这个命名习惯。为了Java的互操作性。将Scala字段加@BeanProperty时,这样会自动生成规范的 setXxx/getXxx方法。这时可以使用对象.setXxx()对象.getXxx()来调用属性。

    注意:给某个属性加入@BeanPropetry注解后,会生成getXXX和setXXX的方法并且对原来底层自动生成类似xxx(),xxx_$eq()方法,没有冲突,二者可以共存

    object ConDemo04 {
      def main(args: Array[String]): Unit = {
    
        val car = new Car
        car.setName("ben")
        println(car.getName)
      }
    }
    class Car{
      @BeanProperty var name :String = null
    
    }
    

    对Car的反编译结果:

    public class Car
    {
      private String name = null;
      public String name() { return this.name; } 
      public void name_$eq(String x$1) { this.name = x$1; } 
      public void setName(String x$1) { this.name = x$1; } 
      public String getName() { return name(); }
    
    }
    

    4、对象创建的流程分析

    1)加载类的信息(属性信息,方法信息)

    2)在内存中(堆)开辟空间

    3)使用父类的构造器(主和辅助)进行初始化

    4)使用主构造器对属性进行初始化

    5)使用辅助构造器对属性进行初始化

    6)将开辟的对象的地址赋给定义的某个引用

  • 相关阅读:
    typeof检测几种较为特殊的值与Boolean强制转换哪几种值为false Amy
    类型检测 Amy
    JS基本概念 Amy
    JS导入文件与CSS导入文件的不同 Amy
    JS运行环境 Amy
    主流浏览器及其渲染引擎 Amy
    JS引用类型 Amy
    同名函数的覆盖问题 Amy
    JS变量、作用域和内存问题 Amy
    HTTP协议学习(1)
  • 原文地址:https://www.cnblogs.com/yxym2016/p/14082770.html
Copyright © 2011-2022 走看看