美文网首页
Scala-类、对象、继承、特质

Scala-类、对象、继承、特质

作者: printf200 | 来源:发表于2019-04-13 13:13 被阅读0次

    1、类
    1、类的定义和访问限制符

    /**
      * 类的定义,变量声明与访问限制
      * 在Scala中,类并不用声明为public。
      *Scala源文件中可以包含多个类,所有这些类都具有公有可见性。
      * Created by 12706 on 2017/11/27.
      */
    //private[scu]:包可见性scu是包名,除了该包和子包其他包不可见
    //Person private表示构造器(无参的主构造器)私有化了,除了伴生对象外其他对象里面一旦创建运行会出错
    private[scu] class Person private {
    
      //val修饰的属性,外部只能访问该属性而不能修改(反编译后能看到只有get方法而没有set方法)
      val id = 110
      //var 修饰的属性,既有get方法也有set方法
      var name = "小明"
    
      //private修饰的属性(类私有字段)只能在当前类(以及伴生对象 object Person)中访问
      private val age : Int = 18
    
      //对象私有字段,访问权限更加严格的,连伴生对象都不能访问,只能当前类才行
      private[this] val height : Int = 16
    
      //getHeight()当然也行
      private def getHeight = {
        height
      }
    
    }
    
    //伴生对象,类和伴生对象之间可以相互访问私有的方法和属性
    object Person {
    
      def main(args: Array[String]): Unit = {
        //创建对象,当然用new Person()也行
        val p = new Person
    
        //访问对象属性,访问不到height属性
        println("id:" + p.id)
        println("姓名:" + p.name)
        println("年龄:" + p.age)
        //通过方法获height属性
        val height = p.getHeight;
        println("身高:" + height)
    
        //修改属性,只能修改到name
        p.name = "小雨"
        println("姓名:" + p.name)
    
      }
    
    }
    
    class Man {}
    object Man {
      def main(args: Array[String]): Unit = {
    //    运行会出错,因为构造器被私有化了
    //   val p = new Person
      }
    }
    

    对上面的demo进行反编译,java代码一目了然

    public class Person
    {
      private final int id = 110;
    
      private String name = "小明";
    
      private final int main$java$cn$scu$scala$day02$Person$$age = 18;
    
      private final int height = 16;
    
      public static void main(String[] paramArrayOfString)
      {
        Person..MODULE$.main(paramArrayOfString);
      }
    
      public int id()
      {
        return this.id;
      }
      public String name() { return this.name; } 
      public void name_$eq(String x$1) { this.name = x$1; }
    
      public int main$java$cn$scu$scala$day02$Person$$age() {
        return this.main$java$cn$scu$scala$day02$Person$$age;
      }
    
      public int main$java$cn$scu$scala$day02$Person$$getHeight()
      {
        return this.height;
      }
    }
    

    2、构造器

    /**
      * 每个类都有主构造器,主构造器的参数直接放置类名后面,与类交织在一起
      * Created by 12706 on 2017/11/27.
      */
    //height : Int 相当于private[this] height : int
    //反编译的时候能看到成员变量有id,name,age
    class People(val id : Int, var name : String, height : Int, private var age : Int = 18)  {
    
    }
    
    object People {
      def main(args: Array[String]): Unit = {
    
        //age有初始值所以创建对象时可以不指定
        val p = new People(1,"小明",60);
        //访问不了height属性,height为对象私有字段
        println(p.id + " " +p.age + " " +p.name)
    
        val p2 = new People(1,"小明",60,28);
        println(p2.id + " " +p2.age + " " +p2.name)
    
      }
    }
    输出
    1 18 小明
    1 28 小明
    
    /**
      * 辅助构造器的定义
      * Created by 12706 on 2017/11/27.
      */
    class Student(val id : Int, val name : String) {
    
      println("执行主构造器!")
    
      //用this关键字定义辅助构造器
      def this(id : Int, name : String, age : Int){
        //每个辅助构造器必须以主构造器或其他的辅助构造器的调用开始
        this(id,name)
        println("执行辅助构造器")
      }
    }
    object Student {
      def main(args: Array[String]): Unit = {
        val stu = new Student(1,"小明",20)
        //同样还是访问不到age的
        println(stu.name)
      }
    }
    
    /**
      * 主构造器会执行类定义中的所有语句
      * Created by 12706 on 2017/11/27.
      */
    class Prop {
    
      println("执行主构造器")
    
      //定义方法
      def method(): Unit ={
        println("用我来读取文件内容 !")
      }
    
      //读取外部文件内容
      try {
        //读取的整个文件后转为String
        val context = Source.fromFile("d://words.txt").mkString
        println(context)
      }catch {
        case e :Exception => e.printStackTrace()
      }finally {
        println("读取文件完毕")
      }
    
    
    }
    object Prop {
      def main(args: Array[String]): Unit = {
          val prop = new Prop
          println("================")
    
          prop.method
      }
    }
    输出
    执行主构造器
    hello tom
    hello jerry
    hello tom
    hello jerry
    hello tom
    hello tom
    读取文件完毕
    ================
    用我来读取文件内容 !
    

    2、对象
    1、单例对象
    在Scala中没有静态方法和静态字段,但是可以使用object这个语法结构来达到同样的目的
    1.存放工具方法和常量
    2.高效共享单个不可变的实例
    3.单例模式

    /**
      * java中SessionFactory(hibernate或者是mybatis(SqlSessionFactory))的设计就是
      * 单例的,通过它来获取Session对象。使用scala来进行简单模拟
      * Created by 12706 on 2017/11/27.
      */
    //下面相当于java的静态块
    object SessionFactory{
      var counts = 5;
      val buffer = new ArrayBuffer[Session](5)
      while (counts>0) {
        //给buffer缓存塞入5个Sessio对象
        val session = new Session
        buffer += session
        counts -= 1
      }
    
      //获取session对象,相当于java的静态方法
      def getSession(): Unit ={
        //缓存中取session
        buffer.remove(0)
      }
    
      def main(args: Array[String]): Unit = {
        //单例对象,不需要new,用【类名.方法】调用对象中的方法
        val session = SessionFactory.getSession
        println(session)
      }
    }
    class Session {
    }
    

    2、伴生对象
    在Scala的类中,与类名相同的对象叫做伴生对象,类和伴生对象之间可以相互访问私有的方法和属性

    /**
      * 伴生对象与类之间私有属性的访问
      * Created by 12706 on 2017/11/27.
      */
    class Dog {
      private val name : String = "旺财"
      def bark(){
        //访问伴生对象的私有属性
        println(Dog.voice)
      }
    }
    object Dog {
     private val voice : String = "wangwang"
    
      def main(args: Array[String]): Unit = {
        val dog = new Dog
        //访问对象的私有name属性
        println(dog.name)
        dog.bark()
      }
    }
    

    2、apply方法

    /**
      * apply方法:通常我们会在类的伴生对象中定义apply方法,
      * 当遇到类名(参数1,...参数n)时apply方法会被调用
      * Created by 12706 on 2017/11/27.
      */
    class Point {
    
      private var x : Int = 2
    
      println("主构造器被调用")
    
      def this(x : Int){
        this()
        this.x = x
      }
    
    }
    
    object Point {
    
      def apply(): Unit ={
        println("apply()方法被调用")
      }
    
      def apply(x : Int, y : Int): Unit = {
        println("apply(x : Int, y : Int)方法被调用")
      }
    
      def apply(x : Int): Point = {
        println("apply(x : Int)方法被调用")
        new Point(x)
      }
    
      def main(args: Array[String]): Unit = {
    
        val p1 = new Point
        println("===================")
        //注意两者区别,调用apply方法的时候不会执行主构造器方法
        val p2 = Point()
    
        val p3 = Point(3,4)
        println("===================")
    
        val p4 = Point(3)
        println(p4.x)
      }
    }
    输出
    主构造器被调用
    ===================
    apply()方法被调用
    apply(x : Int, y : Int)方法被调用
    ===================
    apply(x : Int)方法被调用
    主构造器被调用
    3
    

    4、应用程序对象
    Scala程序都必须从一个对象的main方法开始,可以通过扩展App特质,不写main方法。

    /**
      * 应用程序对象,单例对象(或者伴生对象)继承App即可,App中定义了main方法被继承过来了
      * 所以AppDemo中不需要写main方法了
      * Created by 12706 on 2017/11/27.
      */
    object AppDemo extends App{
      val arr = Array(1,2,3,4)
      println(arr.toBuffer)
    }
    

    3、继承
    1、拓展类
    在Scala中扩展类的方式和Java一样都是使用extends关键字,但是并没有使用implements来实现接口,都是用extends。如果继承一个类的同时也实现了很多接口,那么用extends 父类 with 接口1 with 接口2 with…
    2、方法的重写
    方法重写就是子类中对父类的方法实现重写。
    java中接口中都是抽象方法,但是scala中可以有实现,而且关键字是trait称为特质。但是重写一个非抽象方法必须使用override关键字。
    3、类型检查和转换
    obj.isInstanceOf[C](scala中) ,obj instanceof C(java中)。obj是不是C类型
    obj.asInstanceOf[C](scala中),(C)obj(java中),obj类型强转为C类型。
    classOf[C](scala中),C.class。获取C类型

    /**
      * Men是Human类(继承类),同时拥有动物的行为(实现接口)
      * Created by 12706 on 2017/11/27.
      */
    //Human是类必须接在extends后面
    class Men extends Human with Animall{
      def say(): Unit = {
        println("大家好,我的名字叫:" + name)
      }
    
      //重写父类已经实现的方法需要加override关键字,父类没实现那么可加可不加
      override def getName(): String = {
        this.name
      }
    }
    object Men {
      def main(args: Array[String]): Unit = {
        val man = new Men
        man.name = "xiaoming"
    
        man.say()
        println(man.getName())
    
        //类型检查
        val b = man.isInstanceOf[Animall]
        println(b)
    
      }
    }
    
    abstract class Human {
      var name : String = _
      def say()
    }
    
    trait Animall {
    
      def getName(): String = {
        "monkey"
      }
    }
    输出
    大家好,我的名字叫:xiaoming
    xiaoming
    true
    

    _ 对变量进行默认初始化,比如var i:Int=_

    相关文章

      网友评论

          本文标题:Scala-类、对象、继承、特质

          本文链接:https://www.haomeiwen.com/subject/yxemuqtx.html