Scala面向对象要点总结

it2025-01-14  6

Scala:完全面向对象的语言

1、 面向对象编程1.1包 -package1.2 导入 - import1.3 类 -class1.4 属性1.5 权限修饰符(重点)1.6 方法1.7 构造方法1.8 创建对象的方法1.9 创建单例模式1.10 抽象类1.11 特质1.11.1java中接口和抽象类说明1.11.2 特质基本介绍1.11.3 特质的使用方式1.11.4 特质的初始化顺序1.11.5 特质功能执行的顺序 1.12 拓展

为什么scala号称万物皆对象?

1、 面向对象编程

scala面向对象的思想和java基本上是一致的。

1.1包 -package

java中的包 -- 包 --1. 声明包(起名):域名反写 + 项目名称 + 模块名 + 程序类型名称 a、什么是域名:www.baidu.com --> baidu.com是域名,www不是域名,所以域名反写为:com.baidu b、程序类型名称:比如util(工具)、core(核心)、test(测试)等包 c、但是在实际的使用过程中,我们基本上是不太关注包名,所以怎么简单怎么来,导致我们在看别人的代码时就会出现下面这种包名:" c.a.b.s.bean.JavaUser06" -- 2. 包的作用 2.1 管理类:将声明的类分门别类的管理起来 -- 我们现在通过类名也可以看出来类的作用,所以管理类的作用就没那么重要,如下: service.UserService => UserService bean.JavaUser06 => BeanJavaUser06 2.2 区分类 :依靠包名进行区分,也没那么重要了,如Date java.sql.Date => SQLDate java.util.Date => UtilDate 2.3 类的访问权限:因为我们不能很好的使用4种管理权限,基本就是public private,所以也就没那么重要了; 2.4 编译类:类的源码程序应该和所在的包名保持一致 --> 这是java的限制 -- 3. 总结:Java语法中,package包语法的作用没有那么强大。所以Scala语言对package语法进行了功能的补充,更加强大。 Scala中的包 -- 1. package和源码文件的物理路径没有关系 a、scala会按照package的声明编译指定路径的class b、当前类编译后会在最后的package所在的包中生成class文件 -- 2. package关键字可以多次声明 a、识别时是自上而下的层级关系。 -- 3. package可以使用层级结构 a、在package包名的后面增加大括号,设定作用域范围以及层级关系 b、子包可以直接访问父包中的内容,无需import导入 -- 在同一源码文件中才有效 -- 4. 包也可以当成对象来使用 a、package中为了和java兼容,默认不能声明属性和函数(方法),声明类是可以的。 b、scala提供了一种特殊的对象声明方式: 包对象,"可以将一个包中共通性的方法或属性在包对象中声明。" c、一个包只能创建一个包对象; d、在包对象中的方法、属性和类可以被包中所有的类使用。

1.2 导入 - import

java中的导入 --1. 导类,不是导包 --2. import static 静态导入,导入类的静态属性和静态方法 java语法中import操作功能比较单一。但是不能舍弃Scala语言在java语法基础上进行扩展。 scala中的导入 -- 1. import 可以声明在任意的位置 import java.sql.Date val date = new Date() -- 2. java中默认导入java.lang包中的类 scala中默认导入的类: 2.1 java.lang包中所有的类 2.2 scala包中的类 2.3 Predef (类似于java中静态导入) -- 3. Scala中的import可以导包 import java.sql val date = new sql.Date(); -- 4. 导入一个包中所有的类 a、scala中使用"下划线"代替java中的星号 import java.util.*; -- java方式 b、上面这种方式会将util包下所有的类加载到方法区吗? 不会,方法区的空间也是有限的,编译器会根据在类中使用了哪个类,会将导包的类进行转换,加载使用到的类。 import java.util._ -- scala中使用下划线代替java中星号,表示当前包下的所有类都要 -- 5. 可以在一行中导入同一个包的多个类。使用一对{}花括号,将需要导入的类写在里面 import java.util.{ArrayList, HashMap} new ArrayList() new HashMap() -- 6. 使用import关键字将包中的类隐藏掉 import java.sql.{Date=>_, Array=>_, _} -- 7. 使用import关键字将指定类起别名 方式一: import java.util.{Date=>UtilDate} new UtilDate() 方式二: type UtilDate = java.util.Date val a : UtilDate = new UtilDate() -- 8. Scala默认import是按照包的相对路径进行导入的。 a、委派机制 - 没起作用。 b、不想使用相对路径,那么可以采用特殊的路径(root)访问,则从最顶层开始查找 println(new _root_.java.util.HashMap()) -- 9. import 可以导入对象。 a、该对象只能是使用"val"声明的 b、样式如下 val user = new user import user._ login() test()

1.3 类 -class

-- scala中 class 与object在编译时的区别 --1. 编译时情况: 1. object 在编译时会产生两个类文件,一个是当前类的文件, 还有一个是单例的类文件 如:User.class, User$.class 2. class 在编译时只会产生当前类的class文件 如:Emp.class -- 2. 修饰区别 1. object:用于修饰伴随着普通的类所产生的一个单例对象,用于模仿java中的静态语法,object中的方法和属性都可以通过类名直接访问,类似于静态语法; 2. class: 用于修饰普通的类。 -- 3. 汇总:后来我们统一将“相同名称”的class,object声明的类做了区分: 1. 使用class声明的类:伴生类 2. 使用object声明的类:伴生对象 -- scala中 class 与 object 在使用上的区别 --1. 声明的方式: 1. class: 如果需要通过对象访问属性或方法,那么就使用"class"声明 2. object: 如果需要通过类名就可以直接访问属性或方法,那么就使用"object"声明 --2. 构建对象 1. class: 需要使用new的方式,由于构造方法无参的原因,小括号可以省略; -- val u = new User() -- val u = new User 2. object: 可以直接使用类名,但是获取的是"伴生对象",不能使用new -- 3. 调用方法 1. class: 使用class声明的类无法通过类名直接访问方法或属性,必须构建对象 2. object: 使用object声明的类可以通过类名直接访问属性或方法。 -- 多态声明 1. Scala中class可以继承(extends)父类 2. 多态 : 一个对象在不同场合下所表示的不同的状态。 -- 多态使用 1. Scala当省略类型,编译器会自动将构建对象的类型进行推断。 2. 如果需要使用多态操作,那么必须显示声明类型。 -- java中class 与 scala中class的区别 --java中 1. 只能有一个public的类; 2. public声明的类名需要和文件名称保持一致; 3. 一个文件可以有多个类; -- scala中 1. 类名与文件名可以不一致; 2. class可以声明在很多位置; 3. 一个文件可以有多个公共的类。 IDEA中,scala不同类型的文件对应不同的图标

图标1:表示这个文件中只有伴生对象和伴生类图标2:表示这个文件中只有伴生类图标3:表示文件内容很复杂图标4:表示这个文件中只有伴生对象图标5:表示这个文件中是包对

1.4 属性

-- 属性 --说明 1. 在类中声明属性就等同于在类中声明局部变量的感觉,可以使用var,val声明; 2. 可以通过对象在外部访问; 3. "变量需要显示的初始化"-- 属性的初始化: 1. 如果想要像java中类的属性初始化一样,需要采用特殊的符号:"下划线"2. 如果属性使用"val"来声明。那么初始值"不能使用下划线",需要显示的赋值; 3. 使用val声明的属性也不能改。 -- 属性 Scala类中声明的属性,不仅仅只有属性,还有其他的内容 从如下的源码和反编译可知: 1. 类中声明的属性,都编译为private权限的属性 a、"val"声明的属性:属性会被直接使用final修饰 private final int age = 10; b、"var"声明的属性:属性只是一个普通的私用变量 private String name; 2. 使用var声明的属性:"提供属性set和get方法" a、有类似于java中bean对象的get方法,用于返回属性的值 public String name() { return this.name } b、有类似于java中bean对象的set方法, 用于设定属性的值 public void name_$eq(String x$1) { this.name = x$1; } 3. 使用val声明的属性:"只提供属性get方法",不可变的属性 a、只有类似于java中bean对象的get方法,用于返回属性的值 public int age() { return this.age; } 4. 在使用属性时: a、因为属性为私有的,所以给属性赋值,其实等同于调用属性的set方法 person.name="zhangsan" --反编译--> person.name_$eq("zhangsan"); b、因为属性为私有的,所以获取属性值,其实等同于调用属性的get方法 val name = person.name --反编译--> String name = person.name(); 源码 object Scala_Variable { def main(args: Array[String]): Unit = { val person = new Person } class Person { val age = 10 var name: String = _ } } 反编译代码 public final class Scala_Variable{ public static void main(String[] paramArrayOfString) { Scala_Variable$.MODULE$.main(paramArrayOfString); } public static class Person { private String name; private final int age = 10; public int age() { return this.age; } public String name() { return this.name; } public void name_$eq(String x$1) { this.name = x$1; } } } -- scala 与java的bean的结合 --java Bean规范: 要求属性的set/get方法起名必须以set,get开头,原因是在框架中,会动态获取属性, 反射调用属性的get方法获取属性值。 --Scala编译生成属性的set,get方法并没有遵循bean规范,这样在很多框架中无法使用。 如果想要scala中的属性符合bean规范,可以采用特殊的注解:"@BeanProperty" //源码: @BeanProperty var name: String = _ //反编译:发现生成满足JavaBean的set和get方法,但方法体内还是调用未加注解前类似java的set和get方法 public String getName() { return name(); } public void setName(String x$1) { name_$eq(x$1); }

1.5 权限修饰符(重点)

java中的四种权限符 1. private : 私有权限, "同类" 2. (default) : 包权限, "同类,同包" 3. protected : 受保护权限, "同类,同包,子类" 4. public : 公共权限, "任意的地方" -- 但是你真的了解这四种权限吗? 1. 声明一个类,那么这个类直接或间接继承于Object类,同时继承object类的方法。 object类的方法权限有:public 、 private 、 protected 三种。 2. 什么是访问权限? 权力与限制 3. 确认是否具有访问权限,屡清楚这两个的关系: a、方法的提供者 b、方法的调用者 4. user.clone(); --> 点不是调用关系,而是从属关系 案例1: package com.atguigu; public class java_object { public static void main(String[] args) { User05 user = new User05(); user.clone(); } } class User05 { private String name ; } /* 深层解析: 1. user.clone(); 是java_object类在main方法中调用了user对象的clone()方法 2. a、方法的提供者: 因为Usero5未重写Clone()方法,所以该方法来自于父类object,java.lang.Object b、方法的调用者: com.atguigu.java_object 3. clone()权限:protected,所以是同类、同包、子类可以调用 4. com.atguigu.java_object 与 java.lang.Object 不是子父类的关系 */ "如何理解不是子父类的关系呢?" 1. 每个类都会将其父类所有的属性和方法加载到自己的类中; 2. 现在com.atguigu.java_object访问User05中的父类(object),那他们两个就不是父子类的关系。 3. 是java_object类在main方法中调用了user对象的clone()方法 //这是关键

scala的权限 Scala : 4种访问权限 private : 私有权限 "同类" private[包名] : 包私有权限,"同类,同包" protected : 受保护权限,"同类,子类" (default) : 公共权限, "任意的地方", scala中没有public关键字 --1. private : 同类 a、如果属性声明为private,那么编译器生成set,get方法时,也会使用private进行修饰。 b、使用@BeanProperty注解后,属性不能声明为private --2. private[包名] :同类,同包 a、中括号中的包名可以向上使用 b、必须在当前包的作用域范围内 --3. protected : 同类,子类 --4. (default) : 公共的 Scala中的源码文件中可以声明多个公共类

1.6 方法

-- 方法: 其实就是类中声明的函数 1. 默认方法 a、java.lang.Object的方法 user.toString user.hashCode() b、scala中提供的方法 user.asInstanceOf[User] user.isInstanceOf[User] 获取对象的类型信息(方法区内存) val clazz: Class[_ <: User] = user.getClass val clazz: Class[User] = classOf[User] c、Predef中的方法 2. 自定义方法 -- 方法 - apply(应用) 1. 作用:apply主要作用用于构建对象; 2. 使用场景:当类的构造方法为私有时,使用new"等同于调用对象的构造方法构建对象"的方式就行不通,那么就可以使用apply的方式; 3. 实现原理:一般用于object伴生对象中构建对象,伴生对象可以访问伴生类的"私有"属性和方法; 4. 细节: a、Scala会自动识别apply方法,所以调用伴生对象的apply方法时,apply方法名可以省略; b、如果不使用new来构建对象,那么等同于调用伴生对象的apply方法; c、如果将伴生对象不使用小括号,那么等同于将伴生对象赋值给变量,而不是调用apply方法; d、apply方法如果想要被编译器自动识别,那么不能省略小括号; e、apply方法主要用于构建对象,但是这个构建对象不一定是当前类的对象; f、apply方法可以重载。 -- 方法的重载 1. 概念: 多个方法名称相同,但是参数列表( 参数个数,参数类型,参数顺序 )不相同的方法之间构成重载 2. 应用 数值类型,在重载的方法中会提升精度。 引用类型,在重载的方法如果找不到对应的类型。会从类树往上查找 -- 方法的重写x` 1. 方法的重写一定要存在父子类。 2. 子类重写父类的方法,子类重写父类相同方法的逻辑 3. 子类重写方法与父类的方法要求:方法名一致,参数列表保持一致,异常范围"子类抛出的异常不能比父类大",访问权限"子类的访问权限不能比父类低" 如下内容,其实就是虚方法调用的原则,对于"成员方法"来说:"编译看左边,运行看右边,但是对于属性来说,运行和编译都看左边。" 4. 既然父类和子类有相同的方法,形成了方法的重写。 5. 那么在调用时,无法确定到底执行哪一个方法,那么需要遵循 动态绑定机制 6. 动态绑定机制 :程序"执行"过程,如果调用了对象的"成员""方法"时, 会将方法和对象的实际内存进行绑定,然后调用。 7. 动态绑定机制和属性无关 //方法的重载 package com.atguigu.Scala_chapter01.scala_chapter06_add /** * @Description ** * @author lianzhipeng * @create 2020-05-26 0:10:07 */ object Scala_Method1 { def main(args: Array[String]): Unit = { val user = test.apply() val b : Byte = 10 user.Method(b) } } object test{ def apply(): test = new test() } class test { // def Method ( b : Byte) ={ // println("bbbb") // } def Method ( b : Char) ={ println("CCCC") } def Method ( b : Int) ={ println("iiii") } // def Method ( b : Short) ={ // println("SSSS") // } } package com.atguigu; /** * @author lianzhipeng * @Description * @create 2020-05-26 0:29:52 */ public class Java_Method { public static void main(String[] args) { Student student = new Student(); //情况1: System.out.println(student.sum());//40 //情况2: Person student1 = new Student(); System.out.println(student1.sum());//40 int i = student1.i; System.out.println(i); // 10 //情况3:注释子类重写的方法,再执行情况2的代码,结果为20 } } class Person { int i = 10 ; public int sum(){ return i + 10 ; } } class Student extends Person { int i = 20 ; // public int sum(){ // return i + 20 ; // } }

1.7 构造方法

-- 构造方法 1. 使用new关键字创建的对象其实等同于调用类的构造方法。 2. Scala是一个完全面向对象的语言。 3. Scala还是一个完全面向函数的语言。 4. Scala中类其实也是一个函数,类名其实就是函数名,"类名后面可以增加括号",表示函数参数列表 5. 这个类名所代表的函数其实就是构造方法,构造函数 6. 构造方法执行时,会完成类的主体内容的初始化。 7. 如果在类名的后面增加private关键字,表示主构造方法私有化,无法在外部使用 -- Scala构造方法只有一个吗? --不是。scala中提供了2种不同类型的构造方法 1. 主构造方法:在类名后加一对小括号的构造方法,可以完成类的初始化 2. 辅助构造方法:为了完成类初始化的辅助功能而提供的构造方法 1.声明方式为:"def this() = {}" 2.在使用辅助构造方法时,必须直接或间接地调用主构造方法 3.辅助构造方法也存在重载的概念 4.辅助构造方法间接调用主构造函数时,"需要保证调用的其他辅助构造函数已经声明过"package com.atguigu.Scala_chapter01.scala_chapter06_add /** * @Description ** * @author lianzhipeng * @create 2020-05-26 1:04:52 */ object Scala_Construct { def main(args: Array[String]): Unit = { val person = new Person ("scala") val person1 = new Person() val person2 = new Person("scala",10) } } class Person (name :String) { def this() = { this("scala") } def this (name: String,age:Int) ={ this() } } -- 构造方法之参数 1. 给构造方法增加参数的目的是什么? 从外部将数据传递到对象的属性中 // java : public User( String name ) { this.username = name } 2. Scala中一般构造方法的参数用于属性的初始化,所以为了减少数据的冗余 可以使用关键字var,val将构造参数当成类的属性来用。 "var可读可写,val可读不可写" 3. 辅助构造方法的参数不能作为属性 package com.atguigu.Scala_chapter01.scala_chapter06_add /** * @Description * * * @author lianzhipeng * @create 2020-05-26 1:04:52 */ object Scala_Construct { def main(args: Array[String]): Unit = { // val person = new Person("scala") // println(person.age) // val person1 = new Person() val person2 = new emp("scala", 10) println(person2.age) //10 val emp = new emp() println(emp.name) //java println(emp.age) //20 val emp1 = new emp("hadoop") println(emp1.name) //hadoop } } class emp(val name: String, var age: Int) { def this() = { this("java", 20) } def this(name: String) = { this(name, 30) } } -- 如果父类有构造方法,怎么办? 构建子类对象时,应该首先构建父类对象,如果父类的构造方法有参 那么子类在构建父类对象也应该传递参数。 -- Scala中如何向父类的构造方法中传参? 在父类名称的后面加括号就可以传参了 package com.atguigu.Scala_chapter01.scala_chapter06_add /** * @Description * * * @author lianzhipeng * @create 2020-05-26 1:04:52 */ object Scala_Construct { def main(args: Array[String]): Unit = { val worker = new Worker("java",30) println(worker.age) println(worker.str) } } class Creature ( var name : String ,val age : Int){ } //方式1 //class Worker extends Creature ("java",20){ // //} //方式2 class Worker (var str :String , var num :Int) extends Creature (str , num){ }

1.8 创建对象的方法

-- 方式1: new -- 方式2: apply -- 方式3: classof -- 方式4: clone 【这种方式的类需要实现cloneable接口】 -- 方式5: 反序列化 代码实现 package com.atguigu.Scala_chapter01.scala_review2 /** * @Description ** * @author lianzhipeng * @create 2020-05-26 18:13:10 */ object Scala1_CreateObject extends Cloneable{ def main(args: Array[String]): Unit = { //创建对象的方法 //方式1 :new val user = new User1 println(user) //方式2 : apply val user1 = User1() println(user1) //方式3 : classof val uclass: Class[User1] = classOf[User1] val user2: User1 = uclass.newInstance() println(user2) //方式4 :clone val value = clone() println(value) //方式5 : 反序列化 } } class User1{ val age = 10 } object User1 { def apply(): User1 = new User1() }

1.9 创建单例模式

总结:声明在object中的属性和方法类似java中的静态方法和静态属性,类加载的时候就会被加载。

步骤: -- java中懒汉式 第一步:私有化构造器 第二步:创建一个私有化的静态属性,并new对象 第三步:创建一个公共的静态方法,返回静态属性 -- scala中 object类中{}的内容只会在初始化的时候加载一次,所以将构建的对象语句放在{}中,并声明为val. object Scala2_SingObject { def main(args: Array[String]): Unit = { //调用获取对象的方法,获取两个对象 val singObject: User2 = User2.singObject val singObject1: User2 = User2.singObject //判断这两个对象的地址值是否相等 println(singObject eq singObject1) //true } } class User2 { } object User2{ //创建一个单例对象,并设置为不可变的 val user = new User2 //创建一个方法,供外部进行调用,返回一个单例对象 def singObject ={ user } }

1.10 抽象类

-- 抽象类、抽象方法、抽象属性 --1. 抽象的理解:抽象的对象一般理解为不完整的对象 抽象类 : 不完整的类 抽象方法 :不完整的方法 只有声明而没有实现的方法 无需使用abstract关键字修饰 抽象属性:不完整的属性,只声明而没有初始化的属性 --2. 抽象类、抽象方法、抽象属性之间的关系 抽象类可以没有抽象方法和抽象属性,有抽象方法或抽象属性的类一定是抽象类 --3. 抽象类的说明 a、抽象类无法直接构造对象,可通过子类构造对象 b、抽象类使用"abstract"修饰。 c、抽象类中可以有完整的方法和完整的属性。 --4. 抽象类与其子类 a、子类只有实现抽象类中的所有抽象方法和抽象属性,才能实例化,否则还是抽象类。 --5. 实现抽象方式的说明 a、如果子类重写父类的"完整方法",需要显示增加override关键字来修饰 b、如果子类重写父类的"抽象方法",需要直接补充完整即可, 或采用override关键字修饰 --6. 实现抽象属性的说明 a、子类重写父类的"完整属性",那么需要增加override关键字修饰,"被重写的属性必须是val声明的" b、子类重写父类的"抽象属性",那么需要将属性补充完整即可 关于抽象属性的说明: a、抽象属性在编译时,不会产生类的属性,而是产生属性的set,get方法,并且方法为抽象的。 b、重写抽象属性,那么等同于普通属性的声明:属性,set,get方法。 "问题:为什么子类重写父类完整的属性只能是val,不能是var" -- 回答:如果采用var声明的属性可以被重写,会产生歧义 解析: 1. Scala中类的属性在编译时,会自动生成私有属性和对应的set,get方法。 2. 详情见下图分析

1.11 特质

1.11.1java中接口和抽象类说明

-- java中: -- 抽象类:将子类共通的内容给抽取出来,放置在父类中 a、父类不能直接构建对象,必须通过子类来创建 b、抽象类一般在"父子继承""方法重写"的时候用的比较多。 -- 接口 :和类不一样,不是一个体系,所以可以多继承 a、将接口理解为规范和规则。如果一个类符合指定的规则,就应该实现接口

1.11.2 特质基本介绍

1. Scala中没有接口的概念,也就没有interface关键字。 2. Scala可以将"多个类中相同的特征"从类里剥离出来,形成特殊的语法结构,称之为“特质” 3. 如果一个类,符合这个特征,那么就可以将这个特征(特质)混入到类中

1.11.3 特质的使用方式

1. 使用"trait"声明; 2. 特质中可以声明抽象方法、抽象属性、以及完整的方法和属性; 3. 特质既可以看做java中的接口,也可以看做java中的抽象类; 4. 如果一个类符合特质,那么可以将特质“混入”到类中, 采用extends关键字,如果这个类将抽象部分全部补全,那么可以实例化,否则属于抽象类。 -- 总结: 1. "trait"关键字 可以声明特质 2. 将trait理解为interface :特质之间可以多继承 3. 将trait理解为抽象类 : 特质也可以继承其他类,也可以被其他类继承,并采用with混入其他的特质 4. 子类继承特质,如果重写特质中的具体方法,需要使用override 5. java中所有的接口在Scala中都当成特质来使用 // 声明特质 trait Operate { // 抽象方法 - 不完整方法 def oper():Unit } class MySQL extends Operate { def oper():Unit = { println("执行mysql数据操作...") } } 特质的应用:动态扩展功能,遵循 OCP 开发原则 1. 特质中不仅仅有抽象方法,还可以有具体方法 2. 如果对象声明后想要扩展功能,怎么办? 3. 特质 (混入with) object Scala4_trait { def main(args: Array[String]): Unit = { //构建对象,并使用with “混入”特质2,则拥有特质2所有的属性和方法,如果特质2中也还有抽象方法,那么也需要进行实现 val user = new User4() with MySQL user.select } } //特质1: trait Operator { //抽象方法 def test () : Unit } //特质2: trait MySQL { //完整方法 def select = { println("执行mysql的数据库操作") } } //类“混入”特质1,并实现了特质1中的抽象方法 class User4 extends Operator { override def test(): Unit = { println("zzzz") } }

1.11.4 特质的初始化顺序

object Scala5_trait { def main(args: Array[String]): Unit = { new SubUser35() // aaaaa // bbbbb // ddddd ==> parent class // ccccc ==> trait // eeeee ==> child class } } trait Parent35 { println("aaaaa") } trait Test35 extends Parent35 { println("bbbbb") } trait SubTest35 extends Parent35 { println("ccccc") } class User35 extends Test35 { println("ddddd") } class SubUser35 extends User35 with SubTest35{ println("eeeee") }

1.11.5 特质功能执行的顺序

1. 类混入多个特质的时候,功能的执行顺序"从右向左" 2. 特质中的super其实有特殊的含义,表示的"不是父特质,而是上级特质"3. 如果想要改变执行顺序,需要指定特质的类型 object Scala5_trait { def main(args: Array[String]): Unit = { new MySQL37().operData() //向日志中向数据库中操作数据 } } trait Operate37 { def operData(): Unit = { println("操作数据") } } trait DB37 extends Operate37 { override def operData(): Unit = { print("向数据库中") super.operData() } } trait Log37 extends Operate37 { override def operData(): Unit = { print("向日志中") //super[Operate37].operData() super.operData() } } class MySQL37 extends DB37 with Log37 { }

1.12 拓展

枚举类 object Scala7_Trait { def main(args: Array[String]): Unit = { println(User7.RED) //red println(User7.YELLOW) //yellow println(User7.BLUE) //blue println(User7.BLUE.id) //3 } } object User7 extends Enumeration { val RED = Value(1, "red") val YELLOW = Value(2, "yellow") val BLUE = Value(3, "blue") } 应用类 //在没有main方法中,通过继承App特质,使程序也可以执行 //在APP特质中有main方法,因为是继承了app特质,所以当前类则具有了main主方法 object Scala6_app extends App { println("xxxx") println("yyyy") }
最新回复(0)