(三)Scala面向对象

leafgood

一.面向对象编程基础

1.1 包

1)声明包:常用命名方式 域名反写+项目名称+模块名+程序类型名称
2)基本语法:和java类似

package cn.leaf.demo03

3)Scala在基础语法上进行了扩展,功能更加强大

  • package关键字嵌套声明
package cn{
  package leaf{
    package demo03{
      object Scala_Object{
        def main(args: Array[String]): Unit = {
          println("demo")
        }
      }
    }
  }
}
  • Scala中包和类的物理路径没有关系
  • 子包可以直接访问父包内容,不需要import导入

示例

package cn{
  package leaf{
    class Test{
      def fun(): Unit ={
        println("test")
      }
    }
    package demo03{
      object Scala_Object{
        def main(args: Array[String]): Unit = {
          // 直接使用父包中的Test类
          val t = new Test()
          t.fun()
        }
      }
    }
  }
}

1.2 导入import

1)基本语法和Java一致
2)Scala同样对import进行扩展

  • import 可以在任意位置使用
object Scala_Object{
  def main(args: Array[String]): Unit = {
    import java.util.ArrayList
    new ArrayList[String]()
  }
}
  • Scala中import可以在同一行导入多个类
import java.util.{List, ArrayList}
  • 屏蔽包
import java.sql.{ Date=>_, Array=>_}
  • 给包起别名
import java.util.{Date=>UtilDate}

1.3 类

Scala中没有static成员存在,但是Scala可以通过某种方式达到使用static成员的目的,这个就是伴生机制。
在语法层面上,把static成员和非static成员用不同的表达方式,就是class和object。

class在编译时只会产生当前类的class文件,其作用就是修饰普通的类。

object在编译时会产生两个类文件,一个是当前类的文件,另一个是单例的类文件,object中的属性和方法都可以通过类名直接访问,类似静态语法。

一般将object声明的类称之为伴生类,对应的单例文件称之为伴生对象。

但通常将相同名称的class、object声明的类进行区分:
使用class声明的类为伴生类
使用object声明的类为伴生对象

1.4 属性

示例

object Scala_Object{
  def main(args: Array[String]): Unit = {
    // 类中声明的属性等同于类中声明局部变量,使用var和val声明
    val person1 = new Person
    person1.name = "张三"
    person1.age = 18
    person1.addr = "Beijing"
  }
}

class Person{
  var name:String = _ // 下划线表示默认初始化
  var age:Int = _
  var addr:String = _
  val heigh = 0 // 如果使用val声明,则需要显示赋值,同时使用val声明的属性也不能修改。
}

Scala类中声明的属性
1)编译时,类中声明的属性都是private
然后同时提供公共方法进行访问
2)编译生成的方法为:

类似java中Bean对象的get方法,用于返回属性的值
类似java中Bean对象的set方法,用于设定属性的值

3)在使用时

因为属性是私有,所以给属性赋值,等同于调用set方法
因为属性是私有,所以获取属性值,等同于调用get方法

4)使用val声明的属性

编译时,属性会被final修饰,使用过程中不提供set方法

5)Scala编译生成get、set方法并不遵循bean规范,这导致在很多框架中无法使用,为了兼容其他框架,可以采用注解@BeanProperty。

@BeanProperty
var name:String = _

构建对象:
1) 使用class声明的类,可以直接使用new的方式

object Scala_Object{
  def main(args: Array[String]): Unit = {
    // new 对象,构造方法无参,则小括号可省略
    val person1 = new Person
  }
}

class Person{

}

2)使用apply构建对象,一般用于object伴生对象中构建对象。
示例

object Scala_Object{
  def main(args: Array[String]): Unit = {
    val person = Person()
    val person2 = Person("张三")
  }
}

class Person{

}

object Person{
  // apply方法可以重载
  def apply(): Person = new Person()

  def apply(name:String): Person = {
    println("Person name==>"+name)
    new Person
  }
}

1.5 访问权限

Scala中有4种访问权限:

  • private: 私有权限,同类中访问
  • private[包名]:包私有权限,同类或同包中访问
  • protected: 受保护的权限,同类中访问或者子类中访问
  • (default) : 公共权限,任意位置,注意Scala中没有public关键字

1.6 方法

Scala中类的方法就是函数,声明方式完全一样,但Scala中的方法具有重载和重写机制,同时调用方法必须通过对象。

1.7 构造方法

当使用new关键字创建对象时,就在调用类的构造方法。
Scala中构造方法有两种类型:
1)主构造方法:在类名后的构造方法
2)辅助构造方法:为完成类的初始化提供的构造方法

class Person(){ // 主构造方法
  var person_name:String = _
  def this(name:String){ // 辅助构造方法
    this()
    person_name = name
  }
}

含有参数的主构造方法

class Person(name:String){ // 主构造方法可以有参数
  // name参数是作为局部变量存在,不能通过对象在外部访问
  // person_name 同样是局部变量,但同时也是类的属性,可以通过对象在外部调用
  // 如果我们需要通过对象访问name属性,那传参时,可以使用val name:String,如下边类Person2
  val person_name:String = name
}

class Person2(val name:String){
  
}

二. 面向对象编程进阶

2.1 继承

这个跟Java没有多少区别,同样是单继承,使用extends关键字

class Person{

}

class Student extends Person{

}

不同之处,如果子类要重写父类的非抽象方法,则必须使用overwrite关键字。
子类重写父类方法后,如果在子类中调用父类的被重写的方法,使用super关键字。

class Person{
  def speak(): Unit ={
    println("Person")
  }
  
}

class Stu extends Person{
  override def speak(): Unit = {
    super.speak()
    println("Student")
  }
}

2.2 封装

面向对象编程,封装大同小异,跟没有多少差异。

2.3 抽象

1)抽象类
在父类中,有某些方法没有实现,子类继承时,需要重写来实现,这类方法就是抽象方法。
而含有抽象方法的类,就是抽象类,需要使用abstract声明,跟Java类似。
抽象类不能实例化。

abstract class Car {
  def car_color():Unit
}

class BaoMa extends Car{
  override def car_color(): Unit = {
    println("red")
    println("blue")
  }
}

2)抽象属性
抽象属性,就是说属性只有声明,而没有初始化
类中存在抽象属性,那么这个类也是抽象类。

抽象属性在编译时,不会产生类的属性,而是产生属性的get、set方法,且都是抽象的。
重写抽象属性,等同于重写普通属性的声明:get、set方法

子类重写父类的抽象属性,那么只需要将属性声明补充完整即可。
子类重写父类的常规属性,则需要使用overwrite关键字修饰。

Scala中类的属性编译时,自动生成私有属性和对应的set、get方法,这点通过反编译可以查到。
示例

abstract class Car {
  // 抽象属性
  var car_height:Int
  // 常规属性
  @BeanProperty
  val car_weight:Int = 20
}

class BaoMa extends Car{
  var car_height: Int = 30
  @BeanProperty
  override val car_weight: Int = 30
}

2.4 特质

Scala没有接口的概念,也就没有interface关键字。
但是Scala提供Trait作为接口来使用,也就是特质。
简单来说,就是Scala能够从多个类中将相同的特征抽离出来,形成特殊的语法结构。
Java中所有的接口都可以当做特质来使用。

1)特质可以看做Interface,类混入特质,就等同于实现接口interface。

示例

// 使用trait关键字声明特质
trait DemoTrait{
  def hello(info:String)
}

// 类使用extends关键字混入特质
class Person extends DemoTrait{
  def hello(info: String): Unit = {
    println("hello"+info)
  }

2)特质中除了定义抽象方法外,还能定义具体方法
示例

object Scala_Object{
  def main(args: Array[String]): Unit = {
    // 声明实例对象,使用with关键字混入特质
    val person = new Person with DemoTrait
    person.hello("world")
  }
}

// 使用trait关键字声明特质
trait DemoTrait{
  def hello(info:String):Unit = {
    println("hello:"+info)
  }
}

class Person{
 
}
阅读 73

踏入IT这个圈子,就成了一名玩家,想要走的更远,就要不断给自己技能加点才行。

114 声望
4 粉丝
0 条评论

踏入IT这个圈子,就成了一名玩家,想要走的更远,就要不断给自己技能加点才行。

114 声望
4 粉丝
宣传栏