• 【Scala】04 对象特性Part1


    1、声明式包管理:

    一个Scala文件可以声明N个包

    包的意义和Java的包管理是一样的

    同样也需要import导入资源声明

    package pkgA {
      import com.oracle.nio.BufferSecretsPermission
    
      object PackageOuter {
        var out : String = "OUTER"
    
      }
    
      package pkgB {
        package pkgC {
    
          object PackageInner {
            def main(args: Array[String]): Unit = {
              println(PackageOuter.out)
              PackageOuter.out = "INNER"
              println(PackageOuter.out)
            }
          }
        }
      }
    }
    
    package pkgE {
    
      package pkgG {
    
        import pkgA.PackageOuter
    
        object gg {
          def main(args: Array[String]): Unit = {
            println (PackageOuter.out)
            PackageOuter.out = "INNER"
            println (PackageOuter.out)
          }
      }
      }
    }

    2、包对象

    Scala可以为每一个包定义一个同名的对象,包对象中定义的成员,可以被这个包下所有的Class和Object访问

    【使用Java原始风格的包管理,包对象一般定义在包下的package.scala文件中,包的对象名和包名一致】

    在其他Scala文件中可以直接访问:

    package cn.dzz
    
    object Main {
    
      def main(args: Array[String]): Unit = {
        // 在包下面可以直接访问
        commonMethod()
        println(commonValue)
      }
    
    }

    如果Package文件是复合的,也是一样

    package cn
    // 定义dzz包对象
    package object dzz {
      val commonValue = "1001001"
    
      def commonMethod() = {
        println(commonValue)
      }
    }
    
    
    package ccc {
      import cn.dzz._
      object ddd {
        def main(args: Array[String]): Unit = {
          commonMethod()
          println(commonValue)
        }
      }
    }

    3、导包区别:

    /**
     * 导入包说明
     * 1、可以和Java一样在顶部使用import导入,这个文件中所有导入的类都可以使用
     * 2、局部导入,什么时候调用,什么时候导入,在这个调用的作用域内都可以使用
     * 3、Java导入所有的通配符是*,Scala导入所有通配符是_
     * 4、给类起名 import.java.util.{ArrayList => AL}
     * 5、导入相同包的多个类 import java.util.{HashSet, ArrayList}
     * 6、排除导入的类 import java.util.{ArrayList => _,_}
     * 7、完整名称书写,Java语法 new java.lang.String Scala语法 new _root_.java.util.HashMap
     *
     * 三个默认导入的包资源
     * import.java.lang._
     * import.scala._
     * import.scala.Predef._
     *
     */

    4、类成员的定义:

    // 定义多个类
    class Class1 {
      var name = "alice" // 同样属性也可以有修饰符 不加修饰符默认表示public
    
    
      private var age = 18 // 表示私有的
    
      @BeanProperty // 创建和Java一样的Getter&Setter, 该注解对private修饰是错误的?
      protected var gender = true
    
      // 设定初始值
      var property1:Int = _ // 值放的是下划线,但是必须要声明变量的类型,Scala需要根据类型来推断初始值
      var property2:String = _ // Int初始0 String初始null
    }
    
    class Class2 {
    
    }

    5、封装和访问权限

    package cn
    
    object HelloScala {
      def main(args: Array[String]): Unit = {
        val superClass = new SuperClass
        //  println(superClass.property1) // property1不能被访问, 是被标注为private受保护的
        //  println(superClass.property2) // property2不能被访问, 是被标注为protected受保护的
        println(superClass.property3)
        println(superClass.property4)
    
        superClass.printInfo()
    
        val subClass = new SubClass
        subClass.printInfo()
    
      }
    }
    /**
     * Java 访问权限 public protected (default) private
     * 1、public 可以被公开访问
     * 2、protected 仅限类和继承的子类访问
     * 3、(default) 类和所调用的访问
     * 4、private 只能在类的内部访问
     *
     * Scala 访问权限 (default -> public) protected private
     * 1、Scala默认public 公开访问
     * 2、protected 受保护权限,比Java更严格,同类,子类可以访问,同包无法访问
     * 3、private[包名称] 增加访问权限,包名下的其他类也可以使用
     */
    class SuperClass { // 上级类
      private var property1 : String = "223112312"
      protected var property2 : String = "zhangSan"
      var property3 : Boolean = true
      private [cn] var property4 : Int = 24
    
      def printInfo() = {
        println(s"cn.SuperClass p1 = $property1, p2 = $property2, p3 = $property3, p4 = $property4")
      }
    
    
    }
    
    
    class SubClass extends SuperClass {
    
    
    
      // 重写父类方法
      override def printInfo(): Unit = {
        // 调用父类方法
    //    super.printInfo()
        // 修饰为 private 的 property1 不能被这个SubClass子类访问到
    //    println(s"property1 : $property1") // 这样写报错
    
        property2 = "12"
        property3 = false
        property4 = 100
        super.printInfo()
      }
    
    
    }

    6、构造器 Constructor

    /**
     *  // Scala和Java一样拥有主构造器和辅助构造器
     *
     *  class 类名(形参列表) { // 主构造器
     *    // 类体
     *    def this(形参列表) {
     *      // 辅助构造器1
     *    }
     *    def this(形参列表) {
     *      // 辅助构造器2
     *    }
     *    // 可以有多个辅助构造器 ...
     *  }
     *
     *  1、多个构造器通过重载的形式来进行区分
     *  2、辅助构造器不直接构建对象,必须取调用主构造器实现
     *  3、构造器调用其他另外的构造器,必须 提前声明被调用的构造器
     */
    
    class Student() {
      var name : String = _
      var age : Int = _
      var gender : Boolean = _
    
      println("主构造方法调用")
    
      def this(name : String) {
        this() // 辅助构造器必须要先调用主构造器
        println("辅助构造器1被调用")
        this.name = name
        println(s"name : ${this.name} age : $age gender : $gender")
      }
    
      def this(name : String, age : Int) {
        this(name)
        println("辅助构造器2被调用")
        this.age = age
        println(s"name : ${this.name} age : $age gender : $gender")
      }
    
      def this(name : String, age : Int, gender : Boolean) {
        this(name, age)
        println("辅助构造器2被调用")
        this.gender = gender
        println(s"name : ${this.name} age : $age gender : $gender")
      }
    
      def Student(): Unit = {
        println("对象一般方法被调用")
      }
    
    }

    调用时:

    object HelloScala {
      def main(args: Array[String]): Unit = {
    
        val student = new Student
        student.Student()
      }
    }

    关于构造器参数:

    package cn
    
    object HelloScala {
      def main(args: Array[String]): Unit = {
        val student = new Student("张三", 24, true)
        // 调用打印的时候可以发现这个模板语法就不能打印student.name了 因为name不是成员属性
        //    println(s"student = {name : ${student.name}, age : ${student.age}, gender : ${student.gender}}")
        // student.gender = false // gender 设定为val常量,只允许在构造器调用时赋值一次
    
    
      }
    }
    
    /**
     * 构造器参数问题
     * 参数包括三种类型
     * 1、无任何修饰 该参数是一个局部变量
     * 2、Var修饰 作为类的成员属性使用, 可以写值
     * 3、Val修饰 作为类的成员属性使用, 只读属性
     *
     */
    class Student
    (
    name : String, // 局部变量
    var age : Int, // 成员属性,可以写值
    val gender : Boolean // 成员属性,只读属性
    ) 

    7、继承关系

    package cn
    
    object HelloScala {
      def main(args: Array[String]): Unit = {
        val son1 = new Son("zhangSan", 18)
        val son2 = new Son("zhangSan", 18, "1003001")
      }
    }
    
    /**
     * 继承和多态
     * class 子类名 extends 父类名 { 类体 }
     * 子类继承父类没有访问限制的属性和方法
     * 继承和Java一样,是单继承的
     */
    class Father() {
      var name : String = _
      var age : Int = _
    
      println("Father 主构造器调用!")
    
      def this(name : String, age : Int) {
        this()
        println("Father 辅助构造器调用!")
        this.name = name
        this.age = age
      }
    
      def printInfo(): Unit = {
        println(s"Father => { name = $name, age = $age }")
      }
    }
    class Son(name : String, age : Int) extends Father {
      var no: String = _
      def this (name : String, age : Int, no : String) {
        this(name, age)
        println("Son 辅助构造器调用!")
        this.no = no
      }
    
      println("Son 主构造器调用!")
    
      override def printInfo(): Unit = {
        println(s"Son => { name = $name, age = $age }")
      }
    }

    如果继承的父类构造器声明的是辅助构造器参数,那么还会调用辅助构造参数

    class Son(name : String, age : Int) extends Father(name, age) 

    8、多态

    package cn
    
    object HelloScala {
      def main(args: Array[String]): Unit = {
        // Scala 进行多态和Java的表达是一样的,需要强制声明引用类型
        val daughter : Mather = new Daughter // 父类引用 指向 子类实例
        daughter.sayHello()
      }
    }
    
    // 多态实现
    class Mather {
      val name : String = "Mather"
      def sayHello() : Unit = println(s"Hello Mather $name")
    }
    class Daughter extends Mather {
      override val name : String = "Daughter"
      override def sayHello() : Unit = println(s"Hello Daughter $name")
    }

    9、抽象类:

    package cn
    
    object HelloScala {
      def main(args: Array[String]): Unit = {
        val s : Common = new Specific
        s.method1()
      }
    }
    
    /**
     * 抽象类
     */
    abstract class Common {
      var property1 : String // 没有赋值或者初始值,这个属性也算抽象
      def method1() : Unit // 抽象方法
    }
    
    class Specific extends Common {
      override var property1 : String = "123456" // 没有赋值或者初始值,这个属性也算抽象
      override def method1() : Unit = {
        // 抽象方法的实现
        println("Common abstract Implement !")
      }
    }

    10、匿名子类,匿名实现类

    package cn
    
    object HelloScala {
      def main(args: Array[String]): Unit = {
        val s : Common = new Common {
          override val property: String = "asdasd"
    
          override def method(): Unit = {
            println("method Implement By anonymous Class!!!")
          }
        }
        
        s.method()
      }
    }
    
    /**
     * 匿名子类
     *
     */
    abstract class Common {
      val property : String
      def method() : Unit
    }

    这张图可以直接看懂,Scala是做了一个动静分离的处理

    Object 就可以表示一个Static修饰

    11、特质(接口)

    package cn
    
    object HelloScala {
      def main(args: Array[String]): Unit = {
        val spec : Spec = new Spec
        spec.sayHello()
        spec.dating()
      }
    }
    
    
    
    class Specific {
      val p1 : String = "initVal"
      var p2 : Int = _
    
      def sayHello(): Unit = println("asdasdas")
    }
    
    // 这个类很奇怪,必须要继承某一个类之后才能实现特质
    class Spec extends Specific with Common {
      val p1: String
      var p2: Int
      override var age: Int = _
    
      override def dating(): Unit = {
        println("asdasd")
      }
    
    
    }
    
    
    /**
     * 特质 TRAIT
     * 这个东西使用来代替Java的接口
     * 多个类具有相同的特质,可以抽取特质独立于类来创建,用关键字trait声明
     * 一个普通类可以混合多个特质
     * trait可以抽象方法和属性,也可以有具体的实现
     */
    
    trait Common {
      var age : Int
      val name : String = "young"
    
      def play() : Unit = {
        println("young man always struggle")
      }
      def dating() : Unit
    }

    动态混入:

    就是直接实现接口完成:

    package cn
    
    object HelloScala {
      def main(args: Array[String]): Unit = {
        // 动态混入 注意这里变量不能指定了
        val specificWithCommon = new Specific with Common {
          override var age: Int = _
          override def dating(): Unit = {
            println("dating impl")
          }
        }
        specificWithCommon.sayHello()
        specificWithCommon.dating()
        println(specificWithCommon.age)
      }
    }
    
    class Specific {
      val p1 : String = "initVal"
      var p2 : Int = _
    
      def sayHello(): Unit = println("asdasdas")
    }
    /**
     * 特质 TRAIT
     * 这个东西使用来代替Java的接口
     * 多个类具有相同的特质,可以抽取特质独立于类来创建,用关键字trait声明
     * 一个普通类可以混合多个特质
     * trait可以抽象方法和属性,也可以有具体的实现
     */
    
    trait Common {
      var age : Int
      val name : String = "young"
    
      def play() : Unit = {
        println("young man always struggle")
      }
      def dating() : Unit
    }
  • 相关阅读:
    轮播效果
    获取用户请求过来的URL
    前端框架——AmazeUI学习
    评论功能——多说插件学习
    SqlServer中——查找杀死阻塞进程
    Java 时区(转)
    大型网站技术演进的思考(转)
    elasticsearch threadpool
    UML 类图
    elasticsearch No node available
  • 原文地址:https://www.cnblogs.com/mindzone/p/15000206.html
Copyright © 2020-2023  润新知