zoukankan      html  css  js  c++  java
  • 【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
    }
  • 相关阅读:
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    SVN分支
    SVN分支
    SVN 版本回退
    SVN 版本回退
    如何在excel中取消合并单元格后内容自动填充?
    如何在excel中取消合并单元格后内容自动填充?
    如何让自己像打王者荣耀一样发了疯、拼了命的学习?
  • 原文地址:https://www.cnblogs.com/mindzone/p/15000206.html
Copyright © 2011-2022 走看看