Scala学习(六)面向对象

面向对象

  • Scala 的面向对象思想和 Java 的面向对象思想和概念是一致的。
  • Scala 中语法和 Java 不同,补充了更多的功能。

Scala包

  • 基本语法:package 包名
  • Scala 包的三大作用(和 Java 一样)
    • 区分相同名字的类
    • 当类很多时,可以很好的管理类
    • 控制访问范围
  • 包的命名:
    • 命名规则:只能包含数字、字母、下划线、小圆点.,但不能用数字开头,也不要使用关键字。
    • 案例实操:demo.class.exec1 //错误,因为 class 关键字
    • 命名规范:一般是小写字母+小圆点
  • 包说明:
    • 说明:Scala 有两种包的管理风格,一种方式和 Java 的包管理风格相同,每个源文件一个包(包名和源文件所在路径不要求必须一致),包名用“.”进行分隔以表示包的层级关系,如com.atguigu.scala。另一种风格,通过嵌套的风格表示层级关系,而这种风格有两个特点:
      • 一个源文件中可以声明多个package
      • 子包中的类可以直接访问父包中的内容,而无需导包
        在这里插入图片描述
        在这里插入图片描述
    • 但是外部包想要访问内部包,就需要导包了
      在这里插入图片描述
  • 包对象:在 Scala 中可以为每个包定义一个同名的包对象,定义在包对象中的成员,作为其对
    应包下所有 class 和 object 的共享变量,可以被直接访问。
    在这里插入图片描述
    • 说明:如果使用的是JAVA的包管理风格的话,则包对象一般定义在其对应包下的Package.Scala文件中,包对象名与包名保持一致
      在这里插入图片描述
      • 如果采用的是嵌套方式的管理包,则包对象可与包定义在同一个文件中,但是要保证包对象与包声明在同一作用域中
        在这里插入图片描述
  • 导包说明:和 Java 一样,可以在顶部使用 import 导入,在这个文件中的所有类都可以使用。
    • 局部导入:什么时候使用,什么时候导入。
    • 通配符导入:import java.util._
    • 给类起名:import java.util.{ArraryList => JL}
    • 导入相同包的多个类:imprt java.util.{HashSet,ArraryList}
    • 屏蔽类:import java.util.{ArraryList => -,-}
    • 导入包的绝对路径:new_root_.java.util.HashMap
    • 注意:Scala中 的三个默认导入分别是
      • import java.lang._
      • import scala._
      • import scala.Predef._
        在这里插入图片描述

类和对象

  • 类:可以看成一个模板

  • 对象:表示具体的事物

  • 定义类:Scala中没有public,一个 .scala 中可以写多个类

  • 基本语法:
    在这里插入图片描述

  • 说明:

    • Scala语法中,类并不声明为public,所有这些类都具有公有可见性(即默认就是public)
    • 一个Scala源文件可以包含多个类
  • 属性:属性是类的一部分

    • 基本语法:[修饰符] var|val 属性名称 [:类型] = 属性值
      • 注:Bean属性(@BeanPropetry) , 可以自动生成规范的setXxx/getXxx方法
        在这里插入图片描述

封装

  • 封装就是把抽象出的数据和对数据的操作封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作,才能对数据进行操作。Java封装操作如下:
    • 将属性进行私有化
    • 提供一个公共的set方法,用于对属性赋值
    • 提供一个公共的get方法,用于获取属性的值
  • Scala中的public属性,底层其实就是private,并通过get方法和set方法对其进行操作。所以就没有像java哪些操作,但是为了有些时候也需要这些操作,scala定义了一个注解(@BeanProperty)进行实现
  • 访问权限
    • Scala中属性和方法的默认访问权限为public,但Scala中无public关键字
    • private为私有权限,只在类的内部和伴生对象中可用
    • protected为受保护权限,Scala中受保护权限比Java中更严格,同类,子类可以访问,同包无法访问
    • private【包名】增加包访问权限,包名下的其他类也可以使用
      在这里插入图片描述
  • 方法
    • 基本语法:def 方法名(参数列表) [:返回值类型] = { 方法体 }
      在这里插入图片描述
  • 创建对象:val | var 对象名 [:类型] = new 类型()
    • val修饰对象,不能改变对象的引用,可以改变对象属性的值
    • var修饰对象,可以修改对象的引用和修改对象的属性值
    • 自动推导变量类型不能多态,所以多态需要显示声明
  • 构造器:和 Java 一样,Scala 构造对象也需要调用构造方法,并且可以有任意多个构造方法。构造器包括:主构造器和辅助构造器
    • 辅助构造器,函数的名称为this,可以有多个,编译器通过参数的个数及类型来区分
    • 辅助构造器方法不能直接构建对象,必须直接或者间接调用主构造方法
    • 构造器调用其他另外的构造器,要求被调用构造器必须提前声明
    • 基本语法:class 类名(形参列表) { // 主构造器 // 类体def this(形参列表) { // 辅助构造器 def this(形参列表) { //辅助构造器可以有多个... }}
      在这里插入图片描述
  • 构造器参数:Scala 类的主构造器函数的形参包括三种类型:未用任何修饰、var 修饰、val 修饰
    • 未用任何修饰符修饰,这个参数就是一个局部变量
    • var 修饰参数,作为类的成员属性使用,可以修改
    • val 修饰参数,作为类只读属性使用,不能修改

继承和多态

  1. 基本语法:class 子类名 extends 父类名
    • 子类继承父类得属性和方法
    • scala是单继承
    • 继承调用顺序:父类构造器-》子类构造器
    • scala中属性和方法都是动态绑定,而java中只有方法为动态绑定
  2. 案例实操:
class Person(nameParam:String){
  var name=nameParam
  var age:Int=_
  def this(nameParam:String,ageParam:Int){
    this(nameParam)
    this.age=ageParam
    println("父类辅助构造器")
  }
  println("父类主构造器")
}

class Emp(nameParam:String,ageParam:Int)extends
  Person(nameParam,ageParam){
  var empNo:Int=_
  def this(nameParam:String,ageParam:Int,empNoParam:Int){
    this(nameParam,ageParam)
    this.empNo=empNoParam
    println("子类的辅助构造器")
  }
  println("子类主构造器")
}
object Test{
  def main(args:Array[String]):Unit={
    new Emp("z3",11,1001)
  }
}

//动态绑定
class Person {
  val name: String = "person"
  def hello(): Unit = {
    println("hello person")
  }
}
class Teacher extends Person {
  override val name: String = "teacher"
  override def hello(): Unit = {
    println("hello teacher")
  }
}
object Test {
  def main(args: Array[String]): Unit = {
    val teacher: Teacher = new Teacher()
    println(teacher.name)
    teacher.hello()
    val teacher1:Person = new Teacher
    println(teacher1.name)
    teacher1.hello()
  }
}

抽象属性和抽象方法

  1. 基本语法:
    • 定义抽象类:abstract class Person()
    • 定义抽象属性:一个属性没有初始化,就是抽象属性val|var name:string
    • 定义抽象方法:只声明而没有实现方法,就是抽象方法def hello():string
  2. 继承和重写:
    • 如果父类为抽象类,那么子类需要将抽象的属性和方法实现,否则子类也需声明为抽象类
    • 重写非抽象方法需要用override修饰,重写抽象方法则可以不加override
    • 子类中调用该父类的方法使用super关键字
    • 子类对抽象属性进行实现,父类抽象属性可以用var修饰
      • 子类对非抽象属性重写,父类非抽象属性只支持val类型,而不支持var
      • 因为var修饰的为可变变量,子类继承之后就可以直接使用,没有必要重写
  3. 匿名子类:和 Java 一样,可以通过包含带有定义或重写的代码块的方式创建一个匿名的子类
abstract class Person {
  val name: String
  def hello(): Unit
}
object Test {
  def main(args: Array[String]): Unit = {
    val person = new Person {
      override val name: String = "teacher"

      override def hello(): Unit = println("hello teacher")
    }
  }
}

单例对象(伴生对象)

  • Scala语言是完全面向对象的语言,所以并没有静态的操作。但是为了能够和java语言交互,就产生了一种特殊的对象来模拟类,该对象为单例对象。若单例对象与类名一致,则称该单例对象这个类的伴生对象,这个类的所有”静态“内容可以放置在它的伴生对象中声明。
  • 基本语法:
	object Person{
		val country:String="China"
	}
  • 说明:
    • 单例对象采用object关键字声明
    • 单例对象对应的类称之为半生类,伴生对象的名称应该和伴生类名一致
    • 单例对象中的属性和方法都可以通过伴生对象名直接调用访问
  • 代码:
    • \当一个类表示一个学生的时候,因为学校是固定的所以不需要输入,这个时候就需要伴生对象
      在这里插入图片描述
    • 加入伴生对象后
      在这里插入图片描述
  • apply方法
    • 说明:

      • 通过伴生对象的apply方法,实现不使用new 方法创建对象
      • 如果想让主构造器变成私有的,可以在()之前加上private
      • apply方法可以重载
      • Scala中obj的语句实际是在调用该对象的apply方法,即object.apply.用以统一面对对象编程和函数式编程的风格
      • 当使用new关键字构建对象时,调用的其实是类的构造方法,当直接使用类名构建对象时,调用的其实是伴生对象的apply方法
    • 代码:

      • 平时我们创建对象的时候,会new一个出来,如下图所示
        在这里插入图片描述
      • 但是当我们想要私有构造方法,像工厂模式一样,不直接创建对象的时候,就不能直接new了
        在这里插入图片描述
    • 所以这个时候就需要apply方法使用了
      在这里插入图片描述
      * apply还有个特性,就是可以省略掉
      在这里插入图片描述

特质

  • Scala语言中,采用特质trait(特质)来代替接口的概念,也就是说,多个类具有相同的特质(特征)时,就可以将这个特质独立出来,采用关键字trait声明。
  • Scala中的trait中既可以有抽象属性和方法,也可以有具体的属性和方法,一个类可以混入多个特质。这种感觉类似于JAVA中的抽象类。
  • Scala引入trait特征,第一可以替代Java的接口,第二个也是对单继承机制的一种补充。
  • 语法:
trait 特质名{
	trait 主体
}
  • 一个类具有某种特质,就意味着这个类满足了这个特质的所有要素,所以在使用时,也采用了extends关键字,如果有多个特质或存在父类,那么需要采用with关键字连接。
  • 基本语法:
    • 没有父类:class 类名 extends 特质1 with 特质2 with 特质3 ...
    • 有父类:class 类名 extends 父类
    • 特质可以同时拥有抽象方法和具体方法
    • 一个类可以混入(mixin)多个特质
    • 所有的 Java 接口都可以当做 Scala 特质使用
    • 动态混入:可灵活的扩展类的功能
      • 动态混入:创建对象时混入 trait,而无需使类混入该 trait
      • 如果混入的 trait 中有未实现的方法,则需要实现
  • 代码:
trait PersonTrait {
  //(1)特质可以同时拥有抽象方法和具体方法
  // 声明属性
  var name: String = _
  // 抽象属性
  var age: Int

  // 声明方法
  def eat(): Unit = {
    println("eat")
  }

  // 抽象方法
  def say(): Unit
}

trait SexTrait {
  var sex: String
}

//(2)一个类可以实现/继承多个特质
//(3)所有的 Java 接口都可以当做 Scala 特质使用
class Teacher extends PersonTrait with java.io.Serializable {
  override def say(): Unit = {
    println("say")
  }

  override var age: Int = _
}

object TestTrait {
  def main(args: Array[String]): Unit = {
    val teacher = new Teacher
    teacher.say()
    teacher.eat()
    //(4)动态混入:可灵活的扩展类的功能
    val t2 = new Teacher with SexTrait {
      override var sex: String = "男"
    }
    //调用混入 trait 的属性
    println(t2.sex)
  }
}
  • 特质叠加:由于一个类可以混入多个特质,且特质中可以有具体的属性和方法,若混入的特质中具有相同的方法,必然会出现继承冲突问题。
    • 第一种,一个类中混入了两个特质具有相同的具体方法,且两个特质之间没有任何关系,如果要解决这个方法,就需要在类中重写冲突方法
    • 第二种,一个类混入两个特质中具有相同的具体方法,且两个特质继承自同一个特质,为了解决这个冲突问题,就需要采用特质叠加的策略
      • 当一个类混入多个特质的时候,scala 会对所有的特质及其父特质按照一定的顺序进行排序,而下面案例中的 super.describe()调用的实际上是排好序后的下一个特质中的 describe() 方法。
        在这里插入图片描述
        • 也就是说,案例中的 super,不是表示其父特质对象,而是表示上述叠加顺序中的下一个特质,即,MyClass 中的 super 指代 Color,Color 中的 super 指代 Category,Category 中的 super指代 Ball。
        • 如果想要调用某个指定的混入特质中的方法,可以增加约束:super[],例如super[Category].describe()。
  • 代码:
trait Ball {
 def describe(): String = {
 "ball"
 }
}
trait Color extends Ball {
 override def describe(): String = {
 "blue-" + super.describe()
 }
}
trait Category extends Ball {
 override def describe(): String = {
 "foot-" + super.describe()
 }
}
class MyBall extends Category with Color {
 override def describe(): String = {
 "my ball is a " + super.describe()
 }
}
object TestTrait {
 def main(args: Array[String]): Unit = {
 println(new MyBall().describe())
 }
}
  • 特质自身类型
    • 说明:自身类型可实现依赖注入得功能
    • 案例实操:
class User(val name: String, val age: Int)
trait Dao {
 def insert(user: User) = {
 println("insert into database :" + user.name)
 }
}
trait APP {
 _: Dao =>
 def login(user: User): Unit = {
 println("login :" + user.name)
 insert(user)
 }
}
object MyApp extends APP with Dao {
 def main(args: Array[String]): Unit = {
 login(new User("bobo", 11))
 }
}

类型检查和转换

  • 说明:
    • obj.isInstanceOf[T]:判断 obj 是不是 T 类型。
    • obj.asInstanceOf[T]:将 obj 强转成 T 类型。
    • classOf 获取对象的类名。
  • 案例实操:
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)
 }
}

枚举类和应用类

  • 说明:
    • 枚举类:需要继承 Enumeration
    • 应用类:需要继承 App
  • 案例实操:
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 Test20 extends App {
 println("xxxxxxxxxxx");
}

Type定义新类型

  • 说明:使用 type 关键字可以定义新的数据数据类型名称,本质上就是类型的一个别名
  • 案例实操:
object Test {
 def main(args: Array[String]): Unit = {
 
 type S=String
 var v:S="abc"
 def test():S="xyz"
 }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Scala是一种多范式编程语言,既可以用于面向对象编程,也可以用于函数式编程,支持静态类型检查和类型推断。它受到Java和Ruby的启发,同时也受到函数式编程语言的影响,如Haskell和Erlang。 ### 回答2: Scala主要是学习以下几种语言: 1. Java:Scala是一种在Java虚拟机上运行的编程语言,并且与Java语言高度兼容。因此,学习Scala需要具备一定的Java基础,包括Java的面向对象编程思想、语法和常用的类库。 2. Functional Programming(函数式编程):Scala是一种支持函数式编程的语言,它引入了许多函数式编程的概念和特性,如高阶函数、不可变性和模式匹配等。因此,学习Scala需要学习一些函数式编程的基本理念和技术。 3. Static Typing(静态类型):与Java类似,Scala是一种静态类型语言,需要声明变量的类型,并且在编译时进行类型检查。因此,学习Scala需要对静态类型语言的基本概念和类型系统有一定的了解。 4. Object-Oriented Programming(面向对象编程):Scala是一种面向对象的语言,支持类、继承、多态等面向对象编程的特性。因此,学习Scala需要熟悉面向对象编程的基本思想和常用的设计模式。 总之,学习Scala需要掌握Java的基础知识、函数式编程的概念和技术,以及静态类型和面向对象编程的思想。这些知识将帮助开发者更好地理解和应用Scala编程语言。 ### 回答3: Scala主要是学习Java和函数式编程的语言。 首先,Scala是一种同时支持面向对象编程和函数式编程的语言。在面向对象方面,它借鉴了Java的语法和面向对象思想,因此熟悉Java的人可以很快上手ScalaScala提供了类、继承、多态和接口等特性,使得开发者可以使用面向对象的方式来组织代码和实现复杂的程序。 其次,Scala也是一种函数式编程语言,它引入了很多函数式编程的概念和特性。函数是Scala中的一等公民,可以作为参数或返回值进行传递。Scala提供了很多高阶函数的概念,比如map、filter和reduce等,这些函数可以很方便地操作集合数据。此外,Scala还支持不可变的数据结构和模式匹配等函数式编程的特性。 由于Scala和Java的紧密联系,学习Scala的过程中,对Java的知识会有帮助。熟悉Java的开发者可以借助Scala的优势来提高开发效率和代码可读性。同时,Scala也为Java开发者提供了平滑迁移的途径,可以逐渐引入Scala的特性和概念,使得代码更加简洁和灵活。 综上所述,学习Scala主要是学习Java和函数式编程的语言。掌握Java的开发者可以更快上手Scala,并且通过学习Scala的函数式编程特性,可以拓展自己的编程思维和方式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值