Scala
1.类和对象
//1. Scala中类和对象的创建 object Demo01 {//单例对象,里边是用来定义静态内容的 //定义一个类 //1. 如果构造器是空的可以省略(),2. 如果类时空的可以省略{} class Person //程序的入口,相当于java中的main方法 def main(args: Array[String]): Unit = { //创建对象 val p=new Person() println(p) } }
2. 成员变量的定义和初始化
/** * 1. 定义一个Person类,包含一个姓名和年龄字段 * 2. 创建一个名为"张三"、年龄为20岁的对象 * 3. 打印对象的名字和年龄 */ object Demo03 { //定义Person类 class Person { //定义成员变量 //var类型可以使用 _来初始化成员变量,val类型只能手动初始化 /** * - String => null * - Int => 0 * - Boolean => false * - Double => 0.0 * - ... */ var name: String = "" var age: Int = _ } def main(args: Array[String]): Unit = { //创建对象 val p = new Person //给成员变量赋值 p.name = "刘亦菲" p.age = 38 println(s"姓名是${p.name},年龄是${p.age}") } }
3. 定义成员方法
package com.itheima.scala.oop object Demo05 { //1.定义customer类 class Customer{ //2.定义Customer中成员变量和方法 //val name:String="" //val name="" var name:String=_ var sex:String=_ //成员方法 //简化版 def printHello(msg:String)= println(msg); } def main(args: Array[String]): Unit = { val c=new Customer c.name="刘亦菲" c.sex="female" println(c.name+" "+c.sex) c.printHello("Hello World") } }
4. 访问修饰符
//演示访问修饰符,scala中没有public object Demo06 { class Person { private var name: String = _ private var age = 0 def getName = this.name def setName(name: String) = this.name = name def getAge = this.age def setAge(age: Int) = this.age = age //private def getNameAndAge()=(this.name,this.age) private def getNameAndAge() = this.name -> this.age } def main(args: Array[String]): Unit = { val p = new Person //下面三行报错 //p.name="刘德华" //p.age="18" //p.getNameAndAge() p.setName("迪丽热巴") p.setAge(19) println(p.getName + " " + p.getAge) } }
5. 类的构造器
A::主构造器
构造器参数列表可以指定默认值
创建实例,调用构造器可以指定字段进行初始化
整个class中除了字段定义和方法定义的代码都是构造代码
//演示主构造器 object Demo07 { class Person(var name:String="",var age:Int=0){ //输出调用主构造器 //类中除了字段定义和成员方法都是构造代码,主构造器执行一次,构造代码执行一次 println("主构造器调用啦") } def main(args: Array[String]): Unit = { val p1=new Person("zhangsan",29) println(p1.name+" "+p1.age) println("-"*20) //创建空对象 val p2=new Person println(p2.name+" "+p2.age) println("-"*20) //只对age赋值 val p3=new Person(age =40) println(p3.name+" "+p3.age) println("-"*20) } }
B:辅助构造器
这个方法的名字为
object Demo08 { class Customer(var name:String="",var address:String=""){ def this(data:Array[String]){ this(data(0),data(1));//这个this()表示调用的是本类的主构造器 } } def main(args: Array[String]): Unit = { //创建对象 //主构造器 val c1=new Customer val c2=new Customer(name="刘亦菲") val c3=new Customer(address="北京") val c4=new Customer("刘德华","香港") //思路二 val c5=new Customer(Array("迪丽热巴","新疆")) println(c5.name+" "+c5.address) } }
6. 单例对象
scala中没有想java中的静态成员,要想定义类似于java中static变量,方法,就要使用到scala中的单例对象--object
A:定义单例对象和其中的方法
在object中定义的成员变量类似于Java的静态变量
可以使用object直接引用成员变量
//演示Scala中的单列对象,类似于java中的静态成员 object Demo09 {//定义了单例对象 对象名:Demo09 object Dog{ var LEG_NUM:Int=4 } //单列对象中定义成员方法 object PrintUtil{ //定义一个方法,用来打印15个减号 def show()=println("-"*15) } def main(args: Array[String]): Unit = { println(Dog.LEG_NUM) PrintUtil.show() } }
B:工具类案例
/** * 编写一个DateUtil工具类专门用来格式化日期时间 * 定义一个方法,用于将日期(Date)转换为年月日字符串,例如:2030-10-05 */ import java.text.SimpleDateFormat import java.util.Date //scala中定义工具类 object Demo10 { object DataUtil { def format(date: Date) = { val sdf = new SimpleDateFormat("yyyy-MM-dd MM:mm:ss") sdf.format(date) } } def main(args: Array[String]): Unit = { print(DataUtil.format(new Date())) } }
7. main方法
scala和Java一样,如果要运行一个程序,必须有一个main方法。而在Java中main方法是静态的,而在scala中没有静态方法。在scala中,这个main方法必须放在一个单例对象中。还有一种方法是继承App特质。
//测试程序的执行,继承app trait(特质的啥意思,可以理解为java中的接口) object Demo12 extends App { println("Hello Scala") }
8. 伴生对象
一个class和object具有同样的名字,这个object称为伴生对象,这个class称为伴生类。
A:定义伴生对象
伴生对象和伴生类在同一个scala源文件中
伴生对象和伴生类可以互相访问private属性
//演示伴生对象 object Demo13 { class CustomerService{//伴生类 def save()=println(CustomerService.name+"保存客户") } object CustomerService{//伴生对象 private var name="CustomerService" } def main(args: Array[String]): Unit = { val cs =new CustomerService cs.save() } }
B:private[this]访问权限
/* *会编译报错,移除[this]就可以访问了 */ class Person(private[this] var name:String) object Person { def printPerson(person:Person): Unit = { println(person.name) } } def main(args: Array[String]): Unit = { val person = new Person("张三") Person.printPerson(person) }
C:apply方法
import com.itheima.scala.oop.Demo14.Person //测试伴生对象的apply方法 让创建对象省去 new的动作 object Demo15 { class Person(var name:String="",var age:Int=0){ } object Person{ def apply(name:String,age:Int)=new Person(name,age) } def main(args: Array[String]): Unit = { val p=new Person("亚索",31) print(p.name+" "+p.age) //可以理解为这是理解糖 val p2=Person("劫",40) //这实际就是调用,上面是简写 val p3=Person.apply("盖伦",37) } }
9. 继承
A:类继承
object Demo16 { //定义父类 class Person{ var name:String="" def getName()=this.name } class Student extends Person //定义子类 def main(args: Array[String]): Unit = { //创建类的对象 val s=new Student s.name="李世民" print(s.getName()) } }
B:单例对象继承
object Demo17 { //定义父类 class Person{ var name:String="" def getName()=this.name } object Student extends Person def main(args: Array[String]): Unit = { //创建类的对象 Student.name="和珅" print(Student.getName()) } }
C:
使用override来重写一个val字段
使用super关键字来访问父类的成员方法
10. 类型判断
A:
asInstanceOf将对象转换为指定类型
object Demo19 { class Person class Student extends Person def main(args: Array[String]): Unit = { val s = new Student if (s.isInstanceOf[Student]) { print("是Student类型") } else { print("不是Student类型对象,现在需要转换为Student") s.asInstanceOf[Student] } } }
B:getClass和classOf
classOf[x]可以精确获取类型
使用==操作符可以直接比较类型
object Demo20 { class Person class Student extends Person def main(args: Array[String]): Unit = { val s: Person = new Student println(s.isInstanceOf[Person]) //只能做大致判断,传入Person类或者其子类都会返回true println(s.getClass == classOf[Person]) //可以做精细化判断,必须指定的类型才会返回true,因为s是new的Student类型对象,不是Person 返回false println(s.getClass == classOf[Student]) } }
11. 抽象类
不完整定义有两种情况:
方法没有方法体(抽象方法)
变量没有初始化(抽象字段)
A:抽象方法
object Demo21 { //定义抽象类表示所有的图形 abstract class Shape { def area(): Double //抽象方法 } class Square(var edge: Double) extends Shape { override def area(): Double = edge * edge } class Rectangle(var length: Double, var width: Double) extends Shape { override def area(): Double = length * width } class Circle(var radius: Double) extends Shape { override def area(): Double = 3.14 * radius * radius } def main(args: Array[String]): Unit = { val s = new Square(5) println(s.area()) val r = new Rectangle(10, 5.2) println(r.area()) var c = new Circle(3) println(c.area()) } }
B:抽象字段
// 定义一个人的抽象类 abstract class Person6 { // 没有初始化的val字段就是抽象字段 val WHO_AM_I:String } class Student6 extends Person6 { override val WHO_AM_I: String = "学生" } class Policeman6 extends Person6 { override val WHO_AM_I: String = "警察" } object Main6 { def main(args: Array[String]): Unit = { val p1 = new Student6 val p2 = new Policeman6 println(p1.WHO_AM_I) println(p2.WHO_AM_I) } }
12. 匿名内部类
object Demo22 { //定义一个抽象类,里面有一个sayHello的抽象方法 abstract class Person { def sayHello(msg: String) } def main(args: Array[String]): Unit = { new Person() { //小括号可以省略不写 override def sayHello(msg: String): Unit = println(msg) }.sayHello("我是通过匿名内部类调用的方法") println("-" * 40) val p = new Person { override def sayHello(msg: String): Unit = println(msg) } p.sayHello("第二种方法调用匿名内部类中的方法") } }
13.
- 特质是scala中代码复用的基础单元
- 它可以将方法和字段定义封装起来,然后添加到类中
- 与类继承不一样的是,类继承要求每个类都只能继承一个超类,而一个类可以添加任意数量的特质。
- 特质的定义和抽象类的定义很像,但它是使用trait关键字
使用
extends
来继承trait(scala不论是类还是特质,都是使用extends关键字)如果要继承多个trait,则使用
with
A:trait作为接口使用
//trait相当于java中的接口 object Demo23 { trait Logger { def log(msg: String) } class ConsoleLogger extends Logger { override def log(msg: String): Unit = print(msg) } def main(args: Array[String]): Unit = { var cl = new ConsoleLogger cl.log("调用你了") } }
//继承多个特质trait object Demo24 { trait MessageSender { def send(msg: String) } trait MessageReceiver { def receive(): String } class MessageWorker extends MessageSender with MessageReceiver { override def send(msg: String): Unit = println(msg) override def receive(): String = "你发的消息我收到了,但是我不同意" } def main(args: Array[String]): Unit = { val mw = new MessageWorker mw.send("我喜欢你很久了") print(mw.receive()) } }
B:定义具体的方法
//演示特质中是可以定义具体方法 object Demo25 { trait Logger { def log(msg: String) = print(msg) } class UserService extends Logger { def add() = log("添加用户") } def main(args: Array[String]): Unit = { val us = new UserService us.add() } }
object Demo26 { trait Logger { val sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E") val TYPE: String def log(msg: String) } class ConsoleLogger extends Logger { override val TYPE: String = "控制台信息" override def log(msg: String): Unit = print(s"${TYPE}${sdf.format(new Date())} ${msg}") } def main(args: Array[String]): Unit = { val con = new ConsoleLogger con.log("我是一条日志信息") } }
D. 使用trait实现模板模式
trait中定义了其他的几个具体方法,会调用抽象方法
其他实现类可以来实现抽象方法
真正调用trait中具体方法的时候,其实会调用实现类的抽象方法实现
package com.itheima.scala.oop object Demo27 { trait Logger { def log(msg: String) def info(msg: String) = log("普通日志" + msg) //具体的输出格式已经定义好了,把要输出的内容交给子类来实现 def warn(msg: String) = log("警告日志" + msg) def error(msg: String) = log("错误日志" + msg) } class ConsoleLogger extends Logger { override def log(msg: String): Unit = println(msg) //函数回调 } def main(args: Array[String]): Unit = { val cl = new ConsoleLogger cl.info("我是普通日志") cl.warn("我是警告日志") cl.error("我是错误日志") } class FileLogger extends Logger { override def log(msg: String): Unit = println("我是写入到文件中的") } }
E:
object Demo28 { trait Logger { def log(msg: String) = print(msg) } class UserService def main(args: Array[String]): Unit = { val us = new UserService with Logger us.log("对象混入调用方法") } }
F:trait实现调用链模式
G:trait的构造机制
每个特质只有
一个无参数
的构造器。一个类继承另一个类、以及多个trait,当创建该类的实例时,它的构造顺序如下:
执行父类的构造器
从左到右
依次执行trait的构造器如果trait有父trait,先构造父trait,如果多个trait有同样的父trait,则只初始化一次
执行子类构造器
object Demo30 { trait Logger { println("执行构造器") } trait MyLogger extends Logger { println("执行MyLogger构造器") } trait TimeLogger extends Logger { println("执行TimeLogger构造器") } class Person { println("执行person构造器") } class Student extends Person with MyLogger with TimeLogger { println("执行Student构造器") } def main(args: Array[String]): Unit = { val s = new Student //1. 限制性父类构造器,2. 在从左往右执行特质构造器 3. 特质如果有父类则限制性父类 } }
H:trait继承class
//trait继承class object Demo31 { class MyUtils { def printMsg(msg: String) = println(msg) } trait Logger extends MyUtils { def log(msg: String) = printMsg(msg) } class Person extends Logger { def sayHello(msg: String) = log(msg) } def main(args: Array[String]): Unit = { val p = new Person p.sayHello("今天最好一行代码") } }