【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 }