面向对象编程包

语法

package com.pac1.pac2.pac3package compackage pac1 {    package pac2 {        package pac3 {            object ScalaPackage {                def test(): Unit = {                    println("test...")                }            }        }    }}

注意

  • 包和类的物理路径没有关系

  • 同一个源码文件中子包可以直接访问父包中的内容,而无需import

  • package也可以看作对象,并声明属性和函数

    package big {  class Test{    def test() :Unit = {      printf("test...")    }  }package object ob_pack{  val name : String = "ob_pack"  def getname(): String = {    name  }}  package ob {    object ob01 {      def main(args: Array[String]): Unit = {        new Test().test()        printf(ob_pack.getname())      }    }  }}

导入

语法

import java.util.Listimport java.util._ // Scala中使用下划线代替Java中的星号

注意

  • import语法可以在任意位置使用

  • 可以导包,而不是导类

    object ScalaImport{    def main(args: Array[String]): Unit = {        import java.util        new util.ArrayList()    }}
  • 可以在同一行中导入相同包中的多个类,简化代码

    import java.util.{List, ArrayList}
  • 可以屏蔽某个包中的类

    import java.sql.{ Date=>_, Array=>_, _ }
  • 可以给类起别名,简化使用

    import java.util.{ArrayList=>AList}
  • 可以使用类的绝对路径而不是相对路径

    import _root_.java.util.ArrayList
  • 默认情况下,Scala中会导入如下包和对象

    import java.lang._import scala._import scala.Predef._

语法

// 声明类:访问权限 class 类名 { 类主体内容 } class User {    // 类的主体内容}// 对象:new 类名(参数列表)new User()

注意

  • 一个源文件中可以声明多个公共类

属性

语法

class User {    var name : String = _ // 类属性其实就是类变量    var age : Int = _ // 下划线表示类的属性默认初始化}

注意

  • 属性其实在编译后也会生成方法

       public static class User {      private String name;      private int age;      public String name() {         return this.name;      }      public void name_$eq(final String x$1) {         this.name = x$1;      }      public int age() {         return this.age;      }      public void age_$eq(final int x$1) {         this.age = x$1;      }   }

访问权限

语法

private : 私有访问权限 => 同类private[包名]: 包访问权限 => 同包,包私有protected : 受保护权限,不能同包 => 受保护的, 同类,子类,没有同包            : 公共访问权限

方法

类的方法其实就是函数,所以声明方式完全一样,但是必须通过使用对象进行调用

object ScalaMethod{    def main(args: Array[String]): Unit = {        val user = new User // new 对象 才可以使用方法        user.login("zhangsan", "000000")    }}class User {    def login( name:String, password:String ): Boolean = {        false    }}

对象

语法

val / var 对象名 [:类型]  = new 类型()var user : User = new User()

补充

生成对象的操作

  • 反射
  • new
  • 反序列化
  • clone

构造方法(class)

语法

构造对象也需要调用类的构造方法来创建。并且一个类中可以有任意多个不相同的构造方法。这些构造方法可以分为2大类:主构造函数与辅助构造函数

class User() { // 主构造函数  ----用于完成类的初始化操作的构造方法称之为主构造方法    var username : String = _   // TODO 在构造参数前使用var或val声明    def this( name:String ) { // 辅助构造函数,使用this关键字声明  ----其他的构造方法就称之为辅助构造方法        this() //  辅助构造方法在执行之前,应该首先调用主构造方法完成类的初始化        username = name}    def this( name:String, password:String ) {        this(name) // 构造器调用其他另外的构造器,要求被调用构造器必须提前声明    }}
// 辅助构造方法可以重载的,并且可以互相调用,但是调用的辅助构造方法应该提前声明    def main(args: Array[String]): Unit = {        new User("zhangsan");  // 先执行父类构造方法    // * 子类所有的 构造函数 默认调用父类的无参构造函数(其实是默认省略掉了一行代码:super(););省略掉的这行super()代码可以自行添加到构造函数的第一行(必须是第一行,否则报错)        // aaaaa        // ccccc        new User()        //aaaaa        //ccccc        //ddddd       }    class Person(s:String) {        println("aaaaa")        def this() {            this("lisi")            println("bbbbb")        }    }    class User(var name:String) extends Person(name){        println("ccccc")        def this() {            this("wangwu")            println("ddddd")        }    }

伴生类与伴生对象(object)

构造方法私有化: 在参数列表前增加private关键字
声明一个公共的,静态的,返回本类型的方法,用于获取对象
scala中没有静态语法,但是可以直接使用java中的静态操作
scala采用了一种特殊的处理方式来代替静态语法 :object
object关键字可以用于创建对象,对象的名字就是声明的名字

使用object关键字声明的类和对象有关系的。这个对象等同于伴随着这个类创建时所产生的,所以将这个对象称之为:伴生对象,这个类称之为伴生类,伴生对象就是一个对象,可以访问伴生类中的所有东西,包括私有的。伴生对象其实就是马丁模拟静态语法所产生的。一般写代码时,将静态语法操作的代码写在伴生对象中,将成员方法或属性写在伴生类中

// 伴生类class Person private () {}// 伴生对象// Person.class// Person$.classobject Person {    def getInstance() : Person = {        new Person()    }}
  • scala中伴生对象就是单例的
  • 伴生对象只需要声明即可,无需构建,所以不需要构造参数列表
  • 单例模式存在一个问题:创建的对象不会被回收,需要显示地回收(设置为null)
  • 如果伴生对象中构建对象的方法名成为apply,编译器可以自动识别的,所以这个方法名可以省略的
//val test1: Test = Test.apply()//val test1 = new Test() // 调用类的构造方法//val test2 = Test()     // 调用的是伴生对象的apply方法//val test3 = Test       // 伴生对象本体class Test() {    println("ttttt")}object Test {    def apply() = {        println("apply")        //new Test()    }}

继承

class Person {}class User extends Person { // 单继承}

封装

封装就是把抽象出的数据和对数据的操作封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作(成员方法),才能对数据进行访问。

  1. 将属性进行私有化
  2. 提供一个公共的set方法,用于对属性赋值
  3. 提供一个公共的get方法,用于获取属性的值

抽象

  • 所谓的抽象其实就是不完整

  • 抽象类,抽象方法

  • 抽象类没有办法直接实例化,需要由子类继承后完成实例化操作

  • 子类继承抽象类后,可以声明为抽象类,也可以将父类的抽象方法补充完整。

  • scala中不完整的方法就是抽象,所以无需增加abstract关键字。

  • 将一个不完整的类称之为抽象类。

    abstract class Person {}
  • 如果一个方法只有声明而没有实现,那么是抽象方法,因为它不完整。

    abstract class Person {    def test():Unit}
  • 如果一个属性只有声明没有初始化,那么是抽象属性,因为它不完整。

    abstract class Person {    var name:String}
  • 子类如果继承抽象类,必须实现抽象方法或补全抽象属性,否则也必须声明为抽象的,因为依然不完整。

    abstract class Person {// 抽象属性:只有声明,没有初始化// 编译时,不会在类中声明属性,而是会声明属性的set,get方法,并且是抽象的。    var name:String}class User extends Person {// 属性:编译时,会在类中声明私有属性,同时提供属性的set,get方法,并且为公共的。    var name : String = "zhangsan"}
  • 子类重写父类的抽象方法,直接补充完整即可

  • 子类重写父类的完整方法,必须添加override关键字

  • 开发时,推荐,只要重写,都添加override

    abstract class User {    def test(): Unit = {    }    def fun():Unit}class Child extends User {    override def test(): Unit = {    }    override def fun():Unit = {    }}
  • 子类可以重写父类的抽象属性

    def main(args: Array[String]): Unit = {    // TODO 面向对象 - 抽象    // 子类可以重写父类的抽象属性,补充完整即可    // 子类可以重写父类的完整属性,那么必须要添加override关键字   // println(new Child().age)    println(new Child().test)}abstract class User {    var name : String    val age : Int = 10    def test(): Unit = {        //age = 30 // 对属性的赋值其实等同于调用属性的set方法        println(age) // 对属性的方法其实等同于调用属性的get方法    }}class Child extends User {    var name : String = "zhangsan" // 重写    override val age : Int = 20}

特质

语法

  • 将多个对象中相同的特征,从对象中剥离出来,形成独立的一个结构,称之为trait(特征)
  • 如果一个对象符合这个特征,那么可以将这个特征加入到这个对象,这个加入的过程,称之为混入(extends)
  • 如果一个类只有一个特征时,采用extends关键字进行混入
  • 但是一个类如果有多个特征,这个时候,第一个特征采用extends,后续采用with
  • 如果类存在父类的场合,并同时具备了某个特征,需要使用extends关键字继承父类,使用with关键字来混入特征
trait 特质名称class 类名 extends 父类(特质1) with 特质2 with特质3trait eat {        def eat():Unit    }    trait Runnable {        def run():Unit    }    class Person extends Object with Runnable {        override def run(): Unit = {            println("run...")        }    }    class Dog extends Runnable {        override def run(): Unit = {            println("run...")        }    }

注意

  • 动态混入

    object ScalaTrait{    def main(args: Array[String]): Unit = {        val mysql = new MySQL with Operator //使用中混入        mysql.insert()    }}trait Operator {    def insert(): Unit = {        println("insert data...")    }}class MySQL {}
  • 初始化叠加

    object ScalaTrait{    def main(args: Array[String]): Unit = {        val mysql = new MySQL    }}trait Operator {    println("operator...")}trait DB {    println("db...")}class MySQL extends DB with Operator{    println("mysql...")}
  • 功能叠加

  • java中不能类的多继承 : 砖石问题
    scala采用了一种功能叠加的方式解决砖石问题
    super不是父特质的意思,是上一级(上一个)的意思

    object ScalaTrait {    def main(args: Array[String]): Unit = {        val mysql: MySQL = new MySQL        mysql.operData()    }}trait Operate{    def operData():Unit={        println("操作数据。。")    }}trait DB extends Operate{    override def operData(): Unit = {        print("向数据库中。。")        super.operData()    }}trait Log extends Operate{    override def operData(): Unit = {        super.operData()    }}class MySQL extends DB with Log {}
  • 初始化问题
    父类的特质 > 父类 > 特质1, 特质2 > 当前类

        new User()    //        bbbb    //        dddd    //        aaaa    //        cccc    trait Test extends Test1{        println("aaaa")    }    trait Test1 {        println("dddd")    }    class Person{        println("bbbb")    }    class User extends Person with Test with Test1 {        println("cccc")    }

补充

  • 类型检查和转换

    class Person{}object Person {    def main(args: Array[String]): Unit = {        val person = new Person        //(1)判断对象是否为某个类型的实例        val bool: Boolean = person.isInstanceOf[Person]        if ( bool ) {            //(2)将对象转换为某个类型的实例            val p1: Person = person.asInstanceOf[Person]            println(p1)        }        //(3)获取类的信息        val pClass: Class[Person] = classOf[Person]        println(pClass)    }}
  • 枚举类和应用类

    object Test {    def main(args: Array[String]): Unit = {        println(Color.RED)    }}// 枚举类object Color extends Enumeration {    val RED = Value(1, "red")    val YELLOW = Value(2, "yellow")    val BLUE = Value(3, "blue")}// 应用类object AppTest extends App {    println("application");}
  • Type定义新类型

    object Test {    def main(args: Array[String]): Unit = {        type S = String        var v : S = "abc"    }}
  • 修改不可变字符串内容 — 不可变指的是地址

    val s = " a b "// 反射:类型信息// 镜子val stringClass: Class[String] = classOf[String]val field: Field = stringClass.getDeclaredField("value")field.setAccessible(true)val obj = field.get(s)val chars: Array[Char] = obj.asInstanceOf[Array[Char]]chars(2) = 'D'println(s)