8 面向对象编程
8.1 scala面向对象概念
scala面向对象的基本用法和java没有区别
object TestOOP{
def main(args: Array[String]): Unit = {
/*
* Java中
* package xxxxx
* import java.util.List //导类
* import java.util.* //导入util包内需要的类,并不是一次性全部导入,是用到哪个类就导入哪个类(编译器完成的)。
* public class XXX extends Parent implements Interface {
* private String name;
* public Int age;
*
* //构造器
* public XXX(){
* }
* public void setName(){}
* public boolean login(){}
* }
*
* */
//面向对象编程
//Scala面向对象的语法和Java基本一致
val user = new User
println(user.name)
println(user.login())
}
//类
class User{
//成员变量,属性
val name : String = "Tom"
//成员方法
def login() : Boolean = {
if ("Tom".eq("Tom"))
true
else
false
}
}
}
8.2 包package
-
1 package关键字可以多次声明
-
2 源码路径和包名没有关系
-
3 package可以嵌套使用
-
4 package包可以当对象使用
创建包对象,包对象内可以声明属性、方法,包对象内定义声明的属性方法,在该包内所有的object和class内都可以使用。
//1 package关键字可以多次声明
package com
package codejiwei
package scala
//2 源码路径和包名没有关系,这个地方的包package可以写任何名字,这样就会编译出对应任何名字
package chaptor6{
//3 package可以嵌套声明
package xxx{
object TestObject_Package {
def main(args: Array[String]): Unit = {
//面向对象编程-包-package
//Java中package的作用
// 1 管理类
// 2 权限管理
// 3 区分相同名称的类 Data Data
// 4 源码路径必须要和包名相同
//包名 : 域名 + 项目名 + 模块名 + 程序类型名
// com.codejiwei.test.user.util
// UtilDate
//Java中package语法功能比较单一,所以scala进行了扩展
//4 将包可以当对象来用,
//这个name就是package对象中声明的属性,那么这个包对象内的定义的属性方法,在该包内所有的object和class内都可以使用。
println(name)
say()
}
}
}
}
8.3 导入import
-
java中import是导类,比如:import java.util.Date;
scala中import是真正的导包。import java.util
-
scala中导入一个包中的所有类(用到的哪个类导入哪个类)
import java.util.util._
因为scala中*用来表示可变参数了
import java.util.List import java.util._ // Scala中使用下划线代替Java中的星号
-
scala中的import可以放在任何位置,而java是只能放在类前面
object ScalaImport{ def main(args: Array[String]): Unit = { import java.util.ArrayList new ArrayList() } }
-
scala中可以在同一行中导入多个类,简化代码
import java.util.{List, ArrayList}
-
scala中可以屏蔽某个包中的类
import java.util._ import java.sql.{ Date=>_, Array=>_, _ }
-
scala中可以给类起别名
import java.util.{ArrayList=>AList} object ScalaImport{ def main(args: Array[String]): Unit = { new AList() } }
-
scala中可以使用类的绝对路径而不是相对路径
Scala中import操作默认使用相对包路径,以当前包为查找基准。
import _root_.java.util.ArrayList
-
scala默认会导入如下包和对象
import java.lang._ import scala._ import scala.Predef._
-
导入对象
导入对象的所有内容
object TestImport { def main(args: Array[String]): Unit = { val user = new User("Tom", 23) //导入对象的所有内容 //在访问这个对象的成员方法和属性时,不需要使用对象去调用 //导入对象功能只能对val声明的对象起作用 import user._ println(name11) println(age11) buy() } class User(val name11 : String, var age11 :Int ){ def buy() = { println("buy.....") } } }
package com.codejiwei.scala.chaptor6
//scala才是真正的导包
import com.codejiwei.scala.chaptor6.java.util.HashMap
import java.util
object TestObject_Import {
def main(args: Array[String]): Unit = {
/*
* 面向对象编程-导入-import
* java => import
* 1. 导入类
* 2. 静态导入
*
* Java中import关键字的功能比较单一,所以scala进行扩展
* 1. 采用下划线代替了星号,代表导入一个包中所有的类(用到哪个类才导入哪个类)
* import java.util._
* 2. import关键可以放置在任意地方
* import java.util.Date
* new Date()
*
* 3. scala才是真正的导包
*
* 4. 将同一个包的类在导入时放置在一起
*import java.util.{List, ArrayList, Map, _}
*
*
* 5. 屏蔽类
* import java.util.Date
import java.sql.{Date => _, _}
new Date()
*
* 6. 给类起别名
* import java.util.{HashMap => JavaHashMap}
*
*
* 7. Scala中import操作使用相对包路径,以当前包为查找的基准路径
* 如果不想使用相对包路径,需要采用特殊操作
var map2 = new _root_.java.util.HashMap()
*
* */
// new util.ArrayList()
//如果自己写的类和jdk的类重名了,怎么办?
//jdk不会使用咱们自己的类,而是采用JDK的类,因为安全
//采用了双亲委派机制
var map = new java.util.HashMap()
println(map) //com.codejiwei.scala.chaptor6.java.util.HashMap@19bb089b
}
}
package java{
package util{
class HashMap{
}
}
}
Java的双亲委派机制
Java中当出现重名的类,编译器会先从启动类加载器->扩展类加载器->应用类加载器。这个顺序去找。
启动类加载器位置:D:\Development_tools\java\jdk8\jre\classes
扩展类加载器位置:D:\Development_tools\java\jdk8\jre\lib\ext\classes
应用类加载器位置:D:\
8.4 类
- 面向对象编程中类可以看成一个模板,而对象可以看成是根据模板所创建的具体事物
- Scala中一个源文件中可以声明多个类
object里面声明的属性,方法;模仿的是静态语法
package com.codejiwei.scala.chaptor6
object TestClass {
def main(args: Array[String]): Unit = {
//面向对象编程 - 类
//class类名 {类体}
//在object里面声明的类 没有静态的概念,所以它里面的方法和属性只能通过构建对象才能访问。
//但是声明在object内的属性和方法可以直接通过对象名去访问。
//Scala中一个源文件中可以声明多个类
//子类可以继承父类
val user = new User
user.test()
user.name
val user1 = new User1
user1.name1
user1.test1()
}
class User extends Parent {
val name : String = "Tom"
def test(): Unit ={
println("Test....")
}
}
class Parent{
}
}
8.5 属性
- 所谓的属性就是类中声明的变量,使用var声明的其实是private;使用val声明的其实是private final
-
类的属性可以通过构造对象进行访问
User.name
-
scala中下划线表示类的属性默认初始化
var age : Int = _ //默认初始化,scala中如果不写,表示的是抽象属性。
-
scala中声明属性,同时生成了set、get方法
- scala中给一个属性赋值,其实并不是赋值,而是调用属性的set方法
- scala中访问一个属性,其实并不是访问属性,而是调用属性的get方法
-
因为在很多框架中需要调用类的get和set方法那么怎么办呢?
scala是给属性添加**@BeanProperty**注解的方式,编译器自动生成符合Bean规范的set、get方法
object TestField {
def main(args: Array[String]): Unit = {
//面向对象编程 - 属性
//所谓的属性,其实就是类中声明的变量,private final / private
//使用val声明的普通的变量,那么不会增加final
//使用val声明的类的属性,那么会增加final
//scala中声明属性,等同于java中声明私有的类属性
//外部之所以能够使用,因为编译器在声明属性时,同时生成了属性对应的set、get方法
val user = new User
//scala中给一个属性赋值,其实并不是赋值,而是调用属性的set方法
user.name = "Tom"
//使用val声明的属性,编译器在编译的时候不会提供对应的set方法!!!
// user.password = "root" //声明为val
//scala中获取一个属性,其实并不是访问属性,而是调用属性的get方法
println(user.name)
//如果给属性添加@BeanProperty注解,编译器在生成类时,会自动添加符合Bean规范的set、get方法
}
class User{
@BeanProperty
var name : String = "zhangsan"
@BeanProperty
val password : String = "zhangsan"
}
}
-
声明为var和val的属性其实编译器编译的时候就会生成private和private final的属性,那么在给scala的属性添加private呢
private var name : String = "zhangsan" private val password : String = "zhangsan"
-
如何初始化属性呢?
可以在构造器的参数列表中传递参数,在参数前面添加var或val关键字;scala会将这个参数作为属性来用
class User(var name :String){
}
class User2(){
var name : String = _
def this(name :String){
this()
}
}
8.6 访问权限
- private : 私有访问权限
- private[包名] : 包访问权限
- protected : 受保护权限
- :公共的
package com.codejiwei.scala.chaptor6
import com.codejiwei.scala.chaptor6.test.Parent
object TestObjectAccess {
def main(args: Array[String]): Unit = {
//访问权限
/*
* Java的访问权限
* 1 private :同类
* 2 (default) : 同包同类
* 3 protected : 同类同包子类
* 4 public : 任意
*
* .点:不是调用的意思,表示从属关系
* User user = new User();
* user.name = "zhangsan";
* 1) user对象调用name属性,赋值给zhangsan
* 2) 给user对象的name属性赋值为zhangsan
*
* */
/*
* Scala中的访问权限
* 1 private : 私用
* 2 private[包名] : 包私有访问权限
* 3 protected : 受保护的,只能同类和子类使用,同包不能使用
* 4 (default) : 公共的
*
* */
val p = new Parent
p.sex
}
}
package test{
class Parent {
private val email = "zhang@163.com"
//包私有访问权限的包可以更改
private[chaptor6] val sex = "M"
protected val money = 293.3
def testxx(): Unit ={
println(email)
println(sex)
println(money)
}
}
class Emp extends Parent {
def test1() = {
println(sex)
println(money)
}
}
class User {
def test2() = {
val p = new Parent
println(p.sex)
// println()
}
}
}
8.7 动态绑定机制
动态绑定机制:当调用一个对象的成员方法时,JVM会将这个方法和对象的实际内存进行绑定,然后调用。
属性没有动态绑定机制。
public class Scala07_Object_Method_Java {
public static void main(String[] args) throws Exception {
// 方法的重写
// 子类重写父类的方法
// 动态绑定机制:当调用一个对象的成员方法时,JVM会将这个方法和对象的实际内存进行绑定
// 然后调用,属性没有动态绑定机制
C c = new D();
System.out.println(c.sum());
}
}
class C {
public int i = 10;
public int sum() {
return getI() + 10;
}
public int getI() {
return i;
}
}
class D extends C {
public int i = 20;
// public int sum() {
// return i + 20;
// }
public int getI() {
return this.i;//此时D内有两个i,默认是this.i
}
}
8.8 方法
①方法的重写
子类重写父类的方法
Scala中重写完整方法,需要增加override关键字,但是抽象方法不需要
object Scala11_Object_Abstract {
def main(args: Array[String]): Unit = {
// 抽象 : 不完整
// 不完整的类就是抽象类 : 使用abstract声明的类
// 不完整的方法就是抽象方法 : 只有声明没有实现
//new User()
// 抽象类不能直接构建对象,但是可以由子类继承后,重写抽象方法创建对象
new Child();
// Scala中重写完整方法,需要增加override关键字,但是抽象方法不需要(也可以加,而且更好)
}
abstract class User {
// 抽象方法
def test():Unit
def aaa(): Unit = {}
}
class Child extends User {
override def test():Unit = {}
override def aaa(): Unit = {}
}
}
②方法的重载
方法的重载:方法名相同,凡是参数列表不一样(个数、顺序、类型)
如果指定类型的参数不存在,那么会按照类型下限的方式往上查找类型
public class Scala07_Object_Method_Java_1 {
public static void main(String[] args) throws Exception {
// 方法重载:方法名相同,但是参数列表不一样(个数,顺序,类型)
// 所谓的方法重载,其实就是不同的方法,只是巧了,方法名一样,靠参数列表来区分
// 如果指定类型的参数不存在,那么会按照类型下限的方式往上查找类型。
B a = new B();
test(a);
}
public static void test( A a ) {
System.out.println("aaaaa");
}
// public static void test( B b ) {
// System.out.println("bbbbb");
// }
// public static void test( byte b ) {
// System.out.println("bbbbb");
// }
// public static void test( short s ) {
// System.out.println("sssss");
// }
// public static void test( char c ) {
// System.out.println("cccc");
// }
// public static void test( int i ) {
// System.out.println("iiiii");
// }
}
class A {
}
class B extends A {
}
8.9 对象的创建
构造对象的方式有几种?
-
new 类名()
val user = new User()
-
反射
-
clone
new java.util.ArrayList().clone()
-
反序列化
8.10 构造方法
-
scala中方法名如果和类名相同,并不是构造方法,就是普通方法
-
scala中万物皆对象,万物皆函数
-
类也是函数,在类名后面增加参数列表,其实就是构造函数
-
scala中构造方法主要分为两类:主构造方法(类的初始化)& 辅助构造方法(辅助)
- 1 类名后面的构造方法就是主构造方法
- 2 辅助构造方法主要使用this关键字
- 3 辅助构造方法在执行时,必须显示调用(直接、间接)主构造方法,完成类的初始化
- 4 辅助构造方法存在重载的概念
object TestObjectInstance {
def main(args: Array[String]): Unit = {
//如果构造方法有参数,在构建对象时必须传递构造参数
val user = new User("tom")
//构造方法分为两大类:主构造方法(类的初始化)& 辅助构造方法(辅助)
//1 类名后面的构造方法就是主构造方法
//2 辅助构造方法主要使用this关键字
//3 辅助构造方法在执行时,必须显示调用(直接、间接)主构造方法,完成类的初始化
//4 辅助构造方法存在重载的概念
}
class User(name : String){
println("no para instance...")
def this(){
this(name)
}
def this(i : Int){
this
}
}
}
①存在继承关系的构造方法:
object Scala09_Object_Instance_1 {
def main(args: Array[String]): Unit = {
new User("zhangsan")
}
class Parent(name:String) {
println(name)
}
class User(name:String) extends Parent(name){
}
}
②题目:
结果是:?
object Scala09_Object_Instance_2 {
def main(args: Array[String]): Unit = {
new User()
}
class Parent(name:String) {
println("111111")
def this() {
this("")
println("222222")
}
}
class User(name:String) extends Parent(){
def this() {
this("")
println("33333")
}
println("444444")
}
}
③构造方法私有化
单例模式创建的对象不会释放,除非显示为null
object Scala09_Object_Instance_3 {
def main(args: Array[String]): Unit = {
// 单例模式: 创建对象不会释放,除非显示为null
// 构造方法私有化
//new User()
}
class User private() {
}
}
8.11 单例对象&伴生对象
伴生对象可以直接使用,而无需构建,所以没有构造方法
package com.codejiwei.scala.chaptor6
object TestObjectInstance4 {
def main(args: Array[String]): Unit = {
//单例:scala中采用特殊的方式(object)创建单例对象
//scala中采用object关键字声明类,编译时会编译为2个类
//一个就是当前类本身,另一个就是单例对象的类
//当调用CCC这个object的test()方法时,其实就是调用单例对象CCC$的MODULE$.test()的方法;所以模拟了静态语法
//一般情况下,CCC$这个类称为伴生类,将这个单例对象object称为伴生对象
//一般情况下,将成员方法声明在半生类中
// 将所谓的静态方法声明在半生对象中。
CCC.test()
}
}
8.12 抽象方法
-
抽象方法:不完整的方法,只有声明没有实现
-
抽象方法不能直接创建对象,但是可以子类继承后重写抽象方法,然后创建子类对象。
- 重写抽象方法:可以不加override,但是加上更好
- 重写完整的方法(非抽象方法):必须要加override
object Scala11_Object_Abstract {
def main(args: Array[String]): Unit = {
// 抽象 : 不完整
// 不完整的类就是抽象类 : 使用abstract声明的类
// 不完整的方法就是抽象方法 : 只有声明没有实现
//new User()
// 抽象类不能直接构建对象,但是可以由子类继承后,重写抽象方法创建对象
new Child();
// Scala中重写完整方法,需要增加override关键字,但是抽象方法不需要(也可以加,而且更好)
}
abstract class User {
// 抽象方法
def test():Unit
def aaa(): Unit = {}
}
class Child extends User {
override def test():Unit = {}
override def aaa(): Unit = {}
}
}
8.13 抽象属性
-
不完整的属性就称为抽象属性,只有声明,没有初始化。
抽象属性所在的类是抽象类。
抽象属性其实在编译时,编译成了属性对应的抽象的get、set方法。
-
子类继承父类的抽象属性,需要将属性补充完整
子类在实现父类的抽象属性其实编译时是生成了真正的属性,和两个get和set方法
- 如果希望scala类的属性java一样,有系统默认初始化怎么做?
使用var age : Int = _;使用下划线代替系统默认值
-
完整属性的重写,需要增加override关键字,抽象属性的重写也可以加override,并且最好加上
完整属性的重写,必须声明为val的;抽象属性的重写可以不是val的
object Scala11_Object_Abstract_1 {
def main(args: Array[String]): Unit = {
// 抽象属性
// 不完整的属性就称之为抽象属性:只有声明,没有初始化
// 如果属性不完整,就是抽象属性,对应的类就是抽象类
// 子类继承抽象类,将属性补充完整
// java没有抽象属性的概念,那么scala中抽象属性到底是什么?
// 1. 抽象属性在编译时,不会产生属性的,而是产生了2个抽象的set,get方法
// 2. 子类重写父类的抽象属性时,其实就是产生属性以及实现set,get方法
// 如果希望scala类的属性和java一样,有系统默认初始化怎么做?
// 完整属性的重写,需要增加override关键字
// 完整属性的重写,需要声明为val
new Child()
}
abstract class User {
var name : String
val email : String = null
var age : Int = _
def test(): Unit = {
//email = "wangwu@xxx.com" // setEmail
println(email) //getEmail
}
}
class Child extends User {
var name : String = "zhangsan"
override val email : String = "lisi@xxx.com"
}
}
8.14 apply
-
伴生对象可以访问伴生类的私有属性和方法。
注意:私有的伴生类的形式:
//伴生类 私有的主构造方法 class User private (){ private var name: String = _ var age: Int = _ //伴生类 私有的辅助构造方法 private def this(name: String) = { this() this.name = name } def this(name: String, age: Int) = { this() this.name = name this.age = age } }
-
几种创建对象的方式的区别
// val user = new User //伴生类 // val user1 = new User() //伴生类 // val user2 = User //伴生对象 // val value = User.apply() //.apply()和下面这是一种方式,通过类名.apply()创建对象 // val user = User() //
-
apply创建对象
apply()方法声明在伴生对象中,可以通过类名.apply()或者类名()的方式创建对象
val user1 = User.apply() val user2 = User() object User { def apply(name: String): User = new User(name) def apply(): User = new User() }
object Scala12_Object {
def main(args: Array[String]): Unit = {
// 构造对象
// new => 构造方法
// 伴生对象可以访问伴生类的私有方法和属性的
//val user = new User()
//val user = User.instance()
// Scala提供了其他创建对象的方式:特殊的方法 apply
// apply方法可以被编译器识别,所以可以省略
// apply方法可以重载
//val user1 = User.apply()
//val user2 = User()
//val user3 = User("zhangsan")
//Range(1, 5)
val user1 = new User("zhangsan") // 构造方法
val user2 = User // 伴生对象
val user3 = User() // User.apply()
//println(user1)
//println(user2)
//println(user3)
// apply方法不仅仅可以声明在伴生对象中,还可以声明在伴生类中
// 类名+()表示调用伴生对象的apply方法,对象+()表示调用伴生类的apply方法。
user1.apply()
user1()
}
class User (s:String) {
def : Unit = {
println("kkkkkkkkkkkk")
}
}
object User {
def instance() = {
new User("zhangsan")
}
def apply() = {
println("xxxxxx")
new User("zhangsan")
}
def apply(name : String) = {
println("yyyyyy")
new User(name)
}
}
}
8.15 接口
①面向接口编程
②特征-trait
Scala多个类可能存在相同的特征,那么可以将这个特征从类中剥离出来,形成特殊的结构,然后如果类符合这个特征,那么可以混入这个特征。
Scala采用trait关键字来实现这个特征。
-
trait关键字会在编译的时候被编译为interface
-
如果一个类符合这个特征,可以使用extends的方式将这个特征混入(实现)到类中,在编译的时候会被编译为implements
object TestInterface {
def main(args: Array[String]): Unit = {
val person = new Person
person.run()
}
//run特征
trait run{
//抽象的run方法
def run(): Unit
}
//混入的方式:extends
class Person extends run {
override def run(): Unit = println("person run....")
}
}
- scala中的trait可以简单的理解为接口和抽象类的结合体
//run特征
trait run{
//抽象的run方法
def run(): Unit
//理解为抽象类
def test() = {
println("test....")
}
}
//混入的方式:extends
class Person extends run {
override def run(): Unit = println("person run....")
//那么子类可以重写该抽象方法
override def test(): Unit = println("Test1111")
}
}
③多次混入 with
object TestInterface3 {
def main(args: Array[String]): Unit = {
//如果没有父类可以直接使用extends混入特质
//如果有父类的情况下,可以使用with关键字来混入特质,而且可以多次混入
}
trait run{}
class Parent{}
class User extends Parent with run {}
}
④动态混入功能 with
既然scala编译器编译到最后还是使用的时interface和implements的方式去实现接口,只不过是改变了关键字为trait和extends(with);那么到底还有什么好处呢? — 动态混入功能
有一个场景如果想给User增加一个功能,有几种方法呢?
- OCP原则:open-close-principle开发原则
方式1:直接在User内添加新的功能。这样需要修改源码,违背了OCP原则
方式2:给User创建一个trait特征,让User去混入。但是这样改变了类的体系结构
方式3:动态混入功能!这样可以在不改变类的体系结构的情况下,扩展类的功能。
怎么样动态混入的呢?
首相创建一个新功能的trait特征。然后在创建对象的时候使用动态混入的with关键字加上新功能的trait特征。
object TestInterface2 {
def main(args: Array[String]): Unit = {
/*
* 如果想给User增加一个updateUser的功能
* 方式1:直接在User里面添加一个updateUser()方法,但是这样需要修改源码,违背了OCP原则
* 方式2:给User创建一个trait特征,让User去混入,但是这样改变了类的体系结构
* 方式3:动态混入功能!!!
* */
//方式3 使用with,动态混入原则,可以在不改变类的体系结构的情况下,扩展类的功能,符合OCP开发原则
val user = new User with updateUser
user.updateUser()
}
trait updateUser{
def updateUser() = {
println("updateUser....2")
}
}
//方式2
// class User extends updateUser{
class User {
def insertUser() = {
println("insert user...")
}
//方式1
// def updateUser() = {
// println("update user...")
// }
}
}
⑤ 特质的初始化顺序
- 特质只和当前类相关,和父类、子类都无关,所以父类初始化优先于当前的特质
- 如果将特质理解为抽象类,那么初始化优先于当前类
- 如果一个类混入多个特质,那么多个特质的初始化顺序从左到右
- 特质的初始化只会初始化一次
⑥ 功能叠加顺序
功能的叠加问题,其实就是多个相同功能的调用顺序问题
- 多个特质的初始化顺序是从左到右,但是调用的顺序是从右到左
- super不是父类引用的意思,而是在编译时起到了标记的作用
- scala的功能叠加时,super表示的不是上一级的对象,而是上一个
object TestInterface4 {
def main(args: Array[String]): Unit = {
//功能叠加问题:其实就是多个相同功能的调用顺序问题
val mysql = new MySQL()
mysql.operDate()
/*结果:
* 向数据库中
操作数据
向日志中
操作数据
* */
}
trait Oper {
def operDate() = {
println("操作数据")
}
}
trait DB extends Oper {
override def operDate(): Unit = {
println("向数据库中")
//这样就可以调用两次,一次是直接去调用Oper的operDate方法
super[Oper].operDate()
//另一次就是调用上一个对象也就是Log的operDate方法
super.operDate()
}
}
trait Log extends Oper {
override def operDate(): Unit = {
println("向日志中")
super.operDate()
}
}
//声明的顺序是从左到右,调用的顺序是从右到左。
class MySQL extends Log with DB {
}
}
8.16 拓展
①判断两个对象是否相等一定要重写hashcode和equals方法吗?
不一定!一般情况下只需要重写equals方法就可以了!
只有在往hashmap中放数据的时候,在需要重写hashcode和equals方法。
isInstanceOf[]
这就相当于java中的 instanceof
asInstanceOf[]
这就相当于java中的强制类型转换
//java中判断两个对象是否相等:
public class TestExt {
public static void main(String[] args) {
Dept d1 = new Dept();
d1.id = 1;
Dept d2 = new Dept();
d2.id = 1;
System.out.println(d1 == d2);
System.out.println(d1.equals(d2));
}
}
class Dept{
public int id;
//在hashmap中放数据的时候,才会重写hashcode和equals方法
@Override
public boolean equals(Object obj) {
if (obj instanceof Dept){
Dept other = (Dept)obj;
return id == other.id;
}else {
return false;
}
}
}
//scala中判断两个对象是否相等
object TestEquals {
def main(args: Array[String]): Unit = {
val user = new User
user.name = "Tom"
val user1 = new User
user1.name = "Tom"
println(user==user1)
}
class User{
var name : String = _
override def equals(obj: Any): Boolean = {
//判断obj是否是一个类型的
if (obj.isInstanceOf[User]){
//将obj转换成User类型,赋值给一个新变量
val temp = obj.asInstanceOf[User]
this.name.equals(temp.name)
}else{
false
}
}
}
}
②获取类的信息
object TestClassInfo {
def main(args: Array[String]): Unit = {
//获取类的信息
//类似于Java中User.class和getClass
val value = classOf[User]
val value1 : Class[User] = classOf[User]
}
class User{
}
}
③ 枚举类
object TestEnum {
def main(args: Array[String]): Unit = {
println(Color.BLUE)
}
//scala中的枚举类使用伴生对象object声明;需要继承Enumeration
object Color extends Enumeration{
var RED = Value(1, "red")
var YELLOW = Value(2, "yellow")
var BLUE = Value(3, "blue")
}
}
④ Type定义新类型
使用Type关键字可以定义新的数据类型名称,本质上就是类型的起别名
object Test {
def main(args: Array[String]): Unit = {
type S = String
var v : S = "abc"
}
}