Scala面向对象基本概念

Scala面向对象基本概念


    • 类通过class关键字定义
    • 类通过new关键字创建实例
    • 类拥有成员变量和方法
    • 类的成员默认为public,也支持private,protected
    • 类中无法定义静态成员变量和方法
    • 类无需明确定义构造方法,通过构造参数列表声明为类的一部分
  • 类成员访问修饰符

  • java

    Modifierclasspackagesubclassworld
    publicYYYY
    protectedYYYN
    defaultYNNN
    privateYNNN
  • scala

    Modifierclasscompanionsubclasspackageworld
    defaultYYYYY
    protectedYYYNN
    privateYYNNN
  • 类的定义

    • 构造器

      • 主构造器
      • 辅助构造器
    • 成员变量与方法

    • 类的实例化

      //主构造器执行类定义中的所有语句
      class Point(xc: Int, yc: Int) {
        var x: Int = xc	//成员变量
        var y: Int = yc 
        //辅助构造器
        def this() ={
          this(0, 0)	//第一句必须调用其他构造器
        }
        //成员方法
        def move(dx: Int, dy: Int) ={
          x = x + dx
          y = y + dy
        }  
      }
      var p=new Point()
      p.x
      p.y
      p=new Point(12,11)
      p.x
      p.y
      p.move(1,2)
      
  • 类的继承

    • scala使用extends关键字实现继承

    • 子类重写父类方法必须使用override关键字

      class BlackPoint() extends Point {
          private var color="black"   
          override def move(dx: Int, dy: Int) ={
          x = x + dx
          y = y + dy
          println("moved to x:"+x+" y:"+y)
        }  
      }
      var bp=new BlackPoint()
      bp.x
      bp.y
      bp.move(1,2)
      
  • 抽象类

    • 抽象类可包含未实现的方法,即抽象方法

    • 抽象类无法实例化

    • 抽象类使用abstract关键字修饰

      • 子类重写父类抽象方法时,override关键字可选

      • 子类重写父类非抽象方,override关键子必写

        abstract class Shape{
            def draw():Unit
        }
        class Square extends Shape{
            override def draw():Unit={
                println("draw a square")
            }
        }
        var shape=new Square
        shape.draw
        
  • 单例对象

    • scala的类中无法定义静态成员,即无static关键字

    • 使用object关键字声明,可包含变量,方法与代码定义

    • 单例对象的成员变量,成员方法通过到哪里对象名直接调用

    • 单例对象第一次被访问时初始化,并执行全部代码块

    • 单例对象不能new,且无构造参数

    • 程序入口main()方法必须定义在单例对象中

    • 单例对象与同名类定义在同一文件中形成绑定关系

      //Blah.scala
      package test  //定义包名
      //定义单例对象
      object Blah {
        println("Blah initializing...")
        def sum(l: List[Int]): Int = l.sum
      }
      test.Blah.sum(List[Int](1, 2, 3, 4, 5))
      
  • 伴生

    • 单例对象与同名类定义在同一文件中时形成绑定关系

      • 同名类称为单例对象的伴生类
      • 单例对象称为同名类伴生对象
    • 伴生类与伴生对象可相互访问各自私有成员

    • 伴生对象可为伴生类增加静态成员

      //Student.scala
      //伴生类
      class Student(n: String, a: Int) {
        private var name = n    //私有变量,伴生对象可以访问
        private var age = a
      }
      //伴生对象
      object Student {
        def apply(n: String, a: Int): Student = new Student(n, a)
        def main(args: Array[String]): Unit = {
          val stu=Student("Jason",9)  //通过伴生对象的apply()方法创建实例
          println(stu.name)
        }
      }
      
  • 特质

    • scala中没有接口的概念

    • 特质用于在类之间共享程序接口和字段,类似java接口

    • 特质是字段和方法的集合,可以提供字段和方法实现

    • 类和单例对象都可以扩展特质

    • 特质不能实例化,因此没有构造参数,类似java接口

    • 特质使用trait关键字定义

    • 实现特质中的方法是用override

      import scala.collection.mutable.ArrayBuffer
      
      trait Pet {
        val name: String
        def cry():Unit
      }
      class Dog(val name: String) extends Pet{
        override def cry()=println("wow ...")
      }
      val dog = new Dog("Harry")
      val animals = ArrayBuffer.empty[Pet]
      animals.append(dog)
      animals.foreach(pet => {println(pet.name);pet.cry()})  // Prints Harry wow ...
      
  • 混入特质

    • 当某个特质被用于组合类时,被称为混入

    • 一个类只能由一个父类但是可以有多个混入(分别使用extends和with)

      abstract class A {
        val message: String
      }
      class B extends A {
        val message = "I'm an instance of class B"
      }
      trait C extends A {
        def loudMessage = message.toUpperCase()
      }
      class D extends B with C
      
      val d = new D
      println(d.message)  // I'm an instance of class B
      println(d.loudMessage)  // I'M AN INSTANCE OF CLASS B
      
  • 动态混入特质

    class Drawing { 
      self: Shape =>   (this:Type=> 自身类型,表示该类实例化时必须混入相应特质或子特质,selfthis的别名。
    )
      def start(): Unit = draw()
    }
    trait Shape {
      def draw(): Unit
    }
    trait Square extends Shape {
      def draw(): Unit = println("draw a square")
    }
    trait Triangle extends Shape {
      def draw(): Unit = println("draw a triangle")
    }
    //动态混入
    (new Drawing() with Square).start()
    (new Drawing() with Triangle).start()
    
  • 特质与抽象类的选择

    • 优先使用特质
      • 抽象类只能继承一次
      • 特质可以混入多个
    • 需要使用代餐构造方法时,使用抽象类
    • 与java互操作性
      • 抽象类与java完全可互操作
      • 特质之恶能在不包含任何实现代码时才可互操作
  • 内部类

    • 一个类可以作为另一个类的成员,成为内部类

      • java内部类是外部类的成员

      • scala内部类绑定到外部类的对象实例

        class Graph {
          class Node {
            var connectedNodes: List[Node] = Nil
            def connectTo(node: Node) {
              if (connectedNodes.find(node.equals).isEmpty) {
                connectedNodes = node :: connectedNodes
              }
            }
          }
          var nodes: List[Node] = Nil
          def newNode: Node = {
            val res = new Node
            nodes = res :: nodes
            res
          }
        }
        val g: Graph = new Graph
        val n1: g.Node = g.newNode
        val n2: g.Node = g.newNode
        n1.connectTo(n2)      // legal
        val h: Graph = new Graph
        val n3: h.Node = h.newNode
        n1.connectTo(n3)      // illegal!
        
  • 样例类

    • 样例类常用于描述不可变的值对象

      case class Student(name:String,age:Int)      //定义样例类
      val stu=Student("Jason",19)      //创建样例类的实例,无需new关键字
      println(stu.name)       //访问对象属性                                       
      
      • 样例类构造参数默认声明为val,自动实现类构造参数getter
      • 样例类构造参数声明为var时,自动实现类构造参数setter和getter
      • 阳历类自动创建伴生对象
      • 阳历类自动实现的其他方法
        • toString90,equals(),copy(),hashCode()
        • 伴生对象中的apply(),unapply()
    • 枚举

      object Weekday  extends Enumeration {
        //枚举值从0开始计数
        val Mon,Tue,Wed,Thu,Fri,Sat,Sun=Value
      }
      //枚举的使用
      Weekday.Sun
      Weekday.Sun.id //获取枚举值的计数值
      Weekday.values.foreach(println)
      
    • 样例类与枚举区别

      • 枚举更简单,代码更少

      • 样例类的字段比枚举的值更强大

      • 样例类可扩展

        abstract class Term(code: String)
        case class Var(name: String) extends Term(name)
        case class Fun(arg: String, body: Term) extends Term(arg)
        case class App(f: Term, v: Term) extends Term("App")
        
    • 样例类与普通类

      • 区别
        • 样例类通常用于描述不可变的数据,数据完全依赖构造参数
        • 阳历类默认不可变,通过模式匹配可分解
        • 两个样例类==操作时,通过按值比较而不是按引用
        • 样例类操作更简单
      • 最佳实践
        • 如果一个对象在内部执行有状态计算,或者表现出其他类型的复杂行为,那么它应该是一个普通类
  • 泛型类

    • 泛型类指可以接受类型参数的类,泛型类在集合类中被广泛使用

    • 与java不同,定义泛型类使用[]

      class Stack[T] {
          var elements: List[T] = Nil
          def push(x: T) { elements = x :: elements }
          def top: T = elements.head
          def pop() {
            var t = elements.head
            elements = elements.tail
            t
          }
          def showElements(){
            elements.foreach(x=>print(s"$x "));println()}
        }
      val ms = new Stack[Int]()
      ms.push(10)
      ms.showElements()
      ms.push(20)
      ms.showElements()
      val t = ms.pop()
      ms.showElements()
      
  • 类型边界

    • 在scala中,类型参数可以有一个类型边界约束
    • 类型上界:将类型限制为另一种类型的子类
      • T<:A表示类型变量T应该是类型A的子类
      • A是具体类型,T是泛型
    • 类型下界:将类型声明为另一种类型的超类
      • T>:A表示类型变量T应该是类型A的超类
      • A是具体类型,T是泛型
  • 型变

    • 协变 class Foo[+T]
      • 对于两种类型A和B,如果A是B的子类型,那么Foo[A]就是Foo[B]的子类型
    • 逆变 class Bar[-T]
      • 对于两种类型A和B,如果A是B的子类型,那么Bar[B]就是Bar[A]的子类型
    • 不变 class[T]
      • 默认情况下,scala中的泛型类是不变的
  • 包与包对象

    • scala包:package 包名

      • 只能包含数字,字母,下划线,圆点

      • 不能用数字开头,不能使用关键字

      • 可以在同一个.scala文件中,声明多个并列的package

        package com.233{
        package scala1 {... }
        package scala2 {... }
        }
        package scala3 {... }
        
    • scala包对象

      • 包可以包含类,对象和特质,但不能包含变量或方法的定义,应使用包对象解决这个问题

        package com.233{
        package object scala {	//对应包com.233.scala,每个包都可以有一个包对象
            val name="Wow"
        }...
        package scala{...}//与包对象同名的包可直接使用包对象中定义的变量和方法
        }
        
    • 包引用

      • import让包和包对象的成员可以直接通过名称访问

        //易于访问Fruit
        import 233.Fruit
        //易于访问233的所有成员
        import 233._
        //易于访问233.Fruits的所有成员
        import 233.Fruits._
        //只引用Apple与Orange,并且Apple重命名为McIntosh
        import 233.Fruits.{Apple=>McIntosh,Orange}
        def showFruit(fruit:Fruit){
            import fruit._
            println(name+color)
        }
        
      • import灵活引用

        • 可以出现在任何地方
        • 可以是对象和包
        • 可以重命名或隐藏一些被引用的成员
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值