scala语法(三)(有java基础速学)

news2024/11/27 12:28:53

面向对象编程(中)


scala的包

Scala中包名和源码所在的系统文件目录结构要可以不一致,但是编译后的字节码文件路径和包名会保持一致
在这里插入图片描述


scala 自动引入的包

Scala中,以下三个包的内容会隐式引用到每个程序上。

import java.lang._ // in JVM projects, or system namespace in .NET
import scala._     // everything in the scala package
import Predef._    // everything in the Predef object

scala 包使用注意事项

  1. 在scala中一个文件可以同时创建多个包
  2. 在scala中一个文件可以在不同的包下,创建多个class,object,trait
  3. 包也可以像嵌套类那样嵌套使用(包中有包)
  4. 父包要访问子包的内容时,需要import对应的类等
  5. 可以在同一个.scala文件中,声明多个并列的package(建议嵌套的pakage不要超过3层)
  6. 包名可以相对路径也可以绝对路径
package p1 {
//表示在xxx.p1包下创建了Car的class
  class Car
  
  package p2 {
  	// 父包要访问子包的内容时,需要import对应的类等
    import Test.name
	//表示在xxx.p1.p2包下创建了class Test的伴生类和class Test$的伴生对象 
    object Test {
      // BeanProperty 所在包绝对路径
   	  @_root_.scala.beans.BeanProperty 
      var name: String = _
      def main(args: Array[String]): Unit = {
        print("路径xxx/p1/p2/下")
      }
    }
	//表示在xxx.p1.p2包下创建了Test2的class 
    class Test2
	//表示在xxx.p1.p2包下创建了Test4的特质
    trait Test3

  }

}

包对象

包可以包含类、对象和特质trait,但不能包含函数/方法或变量的定义。这是Java虚拟机的局限。为了弥补这一点不足,scala提供了包对象的概念来解决这个问题 package object 1

  1. 每个包都可以有一个包对象。你需要在父包中定义它
  2. 包对象名称需要和包名一致,一般用来对包的功能补充
package object p1 {
  var name = "jack" //变量
  def sayHi(): Unit = { //方法
    println("package object p1()")
  }
}
package p2 {

  package p3 {

    //这个包下创建了 class Test[伴生类] 和 class Test  [伴生对象]
    object Test {
      def main(args: Array[String]): Unit = {
        //使用对应的包对象的内容
        println("name=" + p1.name)
        p1.sayHi()
        println(p2.p2_name)
      }
    }
  }
}
//p2包功能补充
package object p2{
  var p2_name = "nico" //变量
}
name=jack
package object p1()
nico

scala可见性与修饰符

与java类似

  1. 当属性访问权限为默认时,从底层看属性是private的,但是因为提供了xxx_$eq()[类似setter]/xxx()[类似getter] 方法,因此从使用效果看是任何地方都可以访问)
  2. 当方法访问权限为默认时,默认为public访问权限
  3. private为私有权限,只在类的内部和伴生对象中可用
  4. protected为受保护权限,scala中受保护权限比Java中更严格,只能子类访问,同包无法访问 (编译器从语法层面控制)
  5. 在scala中没有public关键字,即不能用public显式的修饰属性和方法

object Test {
  def main(args: Array[String]): Unit = {
    val clerk = new Clerk
    clerk.showInfo()
    test(clerk)
    //    clerk.name = "zs" //默认修饰符 但提供了Publicd的方法
    //    clerk.age = 10 //访问不到
    //    clerk.job = "hhh" //访问不到
  }
}
//1. 如果我们在同一个文件中,写了 class Clerk 和  object Clerk
//   就把 class Clerk 称为 伴生类, object Clerk 称为伴生对象
//2. 如果我们在同一个文件中,只写了 class Clerk ,那么Clerk就是一个普通的类
//3. 如果我们在同一个文件中,只写了 object Clerk, 那么在底层就会自动生成对应的伴生类 class Clerk, 只是这个伴生类是空..
//4. 伴生对象,可以访问到伴生类的任何方法和属性

class Clerk {
  //var name , 底层 name是private ,但是会提供两个public方法 name name_$eq
  var name: String = "zs"
  //protected var age ,底层 age 是private , 会提供两个pulbic方法 age 和 age_$eq
  protected var age: Int = 10

  private var color: String = "white"

  def showInfo(): Unit = {
    println("showInfo() name=" + name + " age= " + age + " color= " + color) //c.color()
  }

}

object Clerk {
  def test(c: Clerk): Unit = {
    c.name = "ls"
    c.age = 20
    c.color = "red"
    //这里体现出在伴生对象中,可以访问c.sal[sal是私有]
    println("test() name=" + c.name + " age= " + c.age + " color= " + c.color) //c.color()

  }
}
showInfo() name=zs age= 10 color= white
test() name=ls age= 20 color= red

面向对象编程方法——抽象

与java类似,实际上就是把一类事物的共有的属性和行为提取出来,形成一个物理模型(模板)。这种研究问题的方法称为抽象。
如 猫 狗 大象 ==》抽象成动物, 提取属性颜色、年龄 ,提取行为 吃饭、睡觉

在Scala中,通过abstract关键字标记不能被实例化的类。方法不用标记abstract,只要省掉方法体即可。抽象类可以拥有抽象字段,抽象字段/属性就是没有初始值的字段

object Test{
  def main(args: Array[String]): Unit = {
    val mouse: Mouse = new Mouse
    mouse.sayOk()
    mouse.cry()
    println("ok~~")
  }
}

//抽象类
abstract class Animal {
  var name: String //抽象的字段
  var age: Int // 抽象的字段
  var color: String = "black" //普通字段

  def cry() //抽象方法

  def sayOk(): Unit = {
    println("ok")
  }
}

//快捷键 alt+enter
class Mouse extends Animal {

  override var name: String = "Mouse"
  override var age: Int = 10

  //以后再scala中,override 有两层含义 1. 重写(override 必须保留)继承普通类 2. 实现 (可以省略) 继承抽象类
  //  override def cry(): Unit = {
  //
  //  }
  def cry(): Unit = {
    println(name + " " + age)
  }
}

ok
Mouse 10
ok~~

面向对象的三大特征——封装

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

object Test {
  def main(args: Array[String]): Unit = {
    val p = new Person
    p.getInfo()
    
  }
}
class Person{
  private var name: String = _
  private var age: Int = _
  private var salary: Double = _

  def getInfo(): Unit = {
    println(name + " " + age + " " + salary)
  }
}

面向对象的三大特征——继承

写一个非抽象方法需要用override修饰符,调用超类的方法使用super关键字

object Test{
  def main(args: Array[String]): Unit = {
    val t = new Teacher
    t.age = 10
    t.name = "zs"
    t.salary = 10.55
    t.teach
    t.getInfo
  }
}
class Person1 {
  var name: String = _  //name 属性private 底层调用set方法public
  var age: Int = _
  var salary: Double = _

  def getInfo(): Unit = {
    println(name + " " + age + " " + salary)
  }
}
//继承
class Teacher extends Person1 {
  def teach(): Unit = {
  	//调用父类方法
  	super.getInfo()
    println("teach english")
  }
//重写方法
  override def getInfo(): Unit = {
    println(name + "___" + age + "___" + salary)
  }
}
zs
teach english
zs___10___10.55

面向对象的三大特征——多态及类型检查和转换

  1. isInstanceOf,测试某个对象是否属于某个给定的类。
  2. asInstanceOf,将引用转换为子类的引用。
  3. classOf,获取对象的类名。
object TypeConvert {
  def main(args: Array[String]): Unit = {
    // 获取对象类型
    println(classOf[String])
    val s = "zhangsan"
    println(s.getClass.getName) //这种是Java中反射方式得到类型
    println(s.isInstanceOf[String]) //判断类型 true
    println(s.asInstanceOf[String]) //将s 显示转换成String

    val p1: Father = new Son1 //子类对象给了一个父类的引用
    p1.printName()
    p1.asInstanceOf[Son1].say()
    p1.asInstanceOf[Son1].printName1()

    val p2: Father = new Son2 //子类对象给了一个父类的引用
    p2.printName()
    //如果希望使用的子类的方法say
    p2.asInstanceOf[Son2].say()
    p2.asInstanceOf[Son2].printName2()
  }
}

class Father {
  var name = "king"

  def printName(): Unit = {
    println("FatherName=" + name)
  }
}

class Son1 extends Father {
  def say(): Unit = {
    println("Son1=" + name)
  }
  //继承父类 同名方法就得重写
  override def printName(): Unit = {
    println("Son1Name=" + name)
  }
  def printName1(): Unit = {
    println("Son1Name=")
  }
}


class Son2 extends Father {
  def say(): Unit = {
    println("Son2=" + name)
  }
  //继承父类 同名方法就得重写
  override def printName(): Unit = {
    println("Son2Name=" + name)
  }

  def printName2(): Unit = {
    println("Son2Name")
  }
}

class java.lang.String
java.lang.String
true
zhangsan
Son1Name=king
Son1=king
Son1Name=
Son2Name=king
Son2=king
Son2Name

Scala中超类的构造

  1. 类有一个主构器和任意数量的辅助构造器,而每个辅助构造器都必须先调用主构造器
  2. 只有主构造器可以调用父类的构造器。辅助构造器不能直接调用父类的构造器。在Scala的构造器中,你不能调用super(params)
object SuperDemo {
  def main(args: Array[String]): Unit = {
    new Emp5()
  }
}

class Person5(name: String) { //父类的构造器
  println("Person5 主构造器" + name)
}

class Emp5(name: String) extends Person5(name) { // 将子类参数传递给父类构造器,这种写法√
  println("子类的主构造器=" + name)
  //super(name), 错误不能在主构造器中显式的调用super

  def this() {
    this("xxx")
    //super("abc") // (×)不能在辅助构造器中调用显式父类的构造器
  }
}
Person5 主构造器xxx
子类的主构造器=xxx

匿名类

类似java,可以通过包含带有定义或重写的代码块的方式创建一个匿名的子类.

//抽象类,他不能实例化,我们可以通过匿名子类的方式创建一个实例
abstract class Monster {
  var name: String

  def cry()
}

object NoNameClassDemo {
  def main(args: Array[String]): Unit = {

    //匿名子类创建对象实例比较灵活.
    val monster = new Monster {
      override def cry(): Unit = {
        println("啊啊啊啊啊")
      }

      override var name: String = _
    }
    monster.cry()

    val monster1 = new Monster {
      override def cry(): Unit = {
        println("aaaaaaa")
      }

      override var name: String = _
    }
    monster1.cry()
  }
}



啊啊啊啊啊
aaaaaaa

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/88550.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[附源码]Python计算机毕业设计二手交易平台Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等…

如何管理客商主数据,附要点和QA

客商主数据(客户、供应商、既是客户也是供应商)是企业最常用的主数据类型之一。要实现上下游的打通,方便企业内部相关业务的运转以及信息流通,做好客商主数据的管理至关重要。 什么是客商主数据 客商主数据是一类复杂的主数据&a…

一文搞懂Vue Diff算法

为什么需要diff算法? 对于一个容器(比如我们常用的#app)而言,它的内容一般有三种情况: 1.字符串类型,即是文本。 2.子节点数组,即含有一个或者多个子节点 3.null,即没有子节点 在…

【软件开发】前后端分离架构下JWT实现用户鉴权

前后端分离架构下JWT实现用户鉴权在【计算机网络】JWT(JSON Web Token)初识 中,我们讲解了 JWT 的基础知识。Token 验证的方式一般是用在前后端分离的软件开发项目中,所以本篇文章将会从前端和后端的角度去考虑 JWT 的实现。前端 …

H5和小程序的区别

近年来,由于社交电商的火爆程度,相较于传统的电商淘宝、京东、天猫这种第三方平台,其余平台的发展也势不可挡。并且第三方平台的竞争过大,成本过高,抢流量越来越难之后,越来越多的商家企业开始转战H5微商城…

基于知识图谱的多模内容创作技术

导读:由于大数据时代的发展,知识呈指数级增长,而知识图谱技术又在近年来逐步火热,因此诞生了利用知识图谱技术进行智能创作的新想法。本文将分享基于知识图谱的多模内容创作技术及应用。主要包括以下四大部分: 百度知识…

Network Configuration Manager固件漏洞管理

固件漏洞可能会使您的企业和客户的敏感数据面临风险,导致黑客容易进入、销售额下降、声誉损失和处罚。为了避免这些事故,识别这些固件漏洞并定期采取纠正措施非常重要。 使用 Network Configuration Manager,你现在可以识别网络设备中的潜在…

【数据结构-JAVA】包装类 泛型

目录 1. 包装类 1.1 基本数据类型和对应的包装类 1.2 装箱和拆箱 1.3 一道面试题 2. 泛型 2.1 什么是泛型 3. 泛型是如何编译的 3.1 擦除机制 4. 泛型的上界 5. 泛型方法 1. 包装类 在 Java 中,由于基本类型不是继承自 Object,为了在泛型代码中可以…

为什么 FIQ 比 IRQ 的响应速度更快?

目录 1、FIQ在异常向量表位于最末 2、FIQ模式有5个私有寄存器 3、FIQ的优先级高于IRQ 1、FIQ在异常向量表位于最末 一般来说,处理器跳转到异常向量表以后,会根据当前的异常源类型,执行下一次的跳转指令,但是FIQ在异常向量表的…

尚医通:项目搭建-提交到Git(六)

(1)前后端概念介绍 (2)搭建项目后端环境 (3)提交到Git仓库 (1)前后端概念介绍 (2)搭建项目后端环境 项目模块构建 hospital-manage:医院接口模拟…

微服务框架 SpringCloud微服务架构 分布式缓存 44 Redis 分片集群 44.5 RedisTemplate访问分片集群

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式,系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 分布式缓存 文章目录微服务框架分布式缓存44 Redis 分片集群44.5 RedisTemplate访问分片集群44.5.1 RedisTemplate访问分片集群44 Redis 分片…

手把手教你使用SpringBoot做一个员工管理系统【代码篇·上】

手把手教你使用SpringBoot做一个员工管理系统【代码篇上】1.登录功能2.登录拦截器的实现3.展示员工列表1.登录功能 首先把登录页面的表单提交地址写一个controller <form class"form-signin" th:action"{/user/login}">表单的name属性不可少&#…

13、腾讯云轻量应用服务器挂载文件系统

前言&#xff1a;腾讯云轻量应用服务器腾讯云文件存储&#xff08;Cloud File Storage&#xff0c;CFS&#xff09;系统的使用小记 轻量应用服务器系统版本是windows server 2012r 一、必要概念 1.1 轻量应用服务器 轻量应用服务器&#xff08;TencentCloud Lighthouse&#x…

【MySQL】浅谈事务与隔离级别

文章目录1. 事务概述2. 事务的特性3. 事务的隔离级别1. 事务概述 什么是事务&#xff1f; 在MySQL中的事务&#xff08;Transaction&#xff09;是由存储引擎实现的&#xff0c;在MySQL中&#xff0c;只有InnoDB存储引擎才支持事务。事务处理可以用来维护数据库的完整性&#x…

大数据学习--使用Java API访问HDFS

Java API访问HDFS编写Java程序访问HDFS1、创建Maven项目2、添加相关依赖3、创建日志属性文件4、启动集群HDFS服务5、在HDFS上创建文件编写Java程序访问HDFS 1、创建Maven项目 创建Maven项目 - HDFSDemo 单击【Create】按钮 2、添加相关依赖 在pom.xml文件里添加hadoop和…

react的jsx和React.createElement是什么关系?面试常问

1、JSX 在React17之前&#xff0c;我们写React代码的时候都会去引入React&#xff0c;并且自己的代码中没有用到&#xff0c;这是为什么呢&#xff1f; 这是因为我们的 JSX 代码会被 Babel 编译为 React.createElement&#xff0c;我们来看一下babel的表示形式。 需要注意的是…

Kotlin 原生拓展函数与非拓展函数

先看一下图文 根据定义的性质可分为两类 非拓展函数 repeat 循环函数,可使用该函数执行一些有限循环任务,务必在构造函数传入循环次数 repeat(repeatNumber:Int 1) with 条件补充区域,可在某些需要两个或者多个函数对象直接的属性进行依赖操作时使用 …

Python 读取图像方式总结

读取并显示图像 opencv3库scikit-image库PIL库读取图像结果分析 打印图像信息 skimage获取图像信息PIL获取图像信息 读取并显示图像方法总结 PIL库读取图像Opencv3读取图像scikit-image库读取图像参考资料 学习数字图像处理&#xff0c;第一步就是读取图像。这里我总结下如何…

深度学习——CPU,GPU,TPU等硬件说明(笔记)

目录 深度学习硬件&#xff1a;CPU和GPU 深度学习硬件&#xff1a;TPU 深度学习硬件&#xff1a;CPU和GPU 1.提升CPU的利用率Ⅰ&#xff1a;提升空间和时间的内存本地性 ①在计算ab之前&#xff0c;需要准备数据 主内存->L3->L2->L1->寄存器 L1&#xff1a;访…

【LeetCode每日一题:1697. 检查边长度限制的路径是否存在~~~并查集+数组排序+排序记录下标位置】

题目描述 给你一个 n 个点组成的无向图边集 edgeList &#xff0c;其中 edgeList[i] [ui, vi, disi] 表示点 ui 和点 vi 之间有一条长度为 disi 的边。请注意&#xff0c;两个点之间可能有 超过一条边 。 给你一个查询数组queries &#xff0c;其中 queries[j] [pj, qj, li…