Scala编程
继承和抽象类
继承
类型判断
抽象类
通过abstract关键字实现。
定义
如果类中有抽象字段或抽象方法,那么该类就是一个抽象类。
- 抽象字段:没有初始化值的变量
- 抽象方法:没有方法体
格式
1 abstract class 抽象类名{ 2 val/var 抽象字段名:类型 3 def 方法名(参数:参数类型...):返回类型 4 }
抽象案例
示例
1 //目的:抽象类更像是一个空数据模板,如果其他类继承这个抽象类,可以省去写很多抽象字段和方法 2 //细节:抽象类的子类:1.子类如果是抽象类,则不用重写父类的抽象方法。2.如果是普通类,必须重写父类所有抽象方法。 3 //抽象类无法直接创建对象 4 object ClassDemo01 { 5 //添加一个抽象类,计算面积 6 abstract class Shape { 7 def area():Double 8 def a1():Int 9 def a2():Int 10 def a3():Int 11 } 12 //创建正方形类和长方形类,继承自Shape,包含一个主构造器、面积计算方法 13 class Square(var edge : Double) extends Shape { 14 override def area: Double = edge * edge 15 16 override def a1(): Int = ??? 17 18 override def a2(): Int = ??? 19 20 override def a3(): Int = ??? 21 } 22 class Rectangle(var length : Double,var width : Double) extends Shape { 23 override def area(): Double = length * width 24 } 25 26 def main(args: Array[String]): Unit = { 27 val s1 = new Square(5) 28 println(s1.area) 29 } 30 }
匿名内部类
匿名内部类是继承了类的匿名子类对象,可直接用来创建实例对象。
语法
1 new 类名(){ 2 //重写类中所有的抽象内容 3 }
使用场景
- 当对对象方法(成员方法)仅调用一次时;
- 可作为方法参数进行传递;
示例
- 创建一个Person抽象类,并添加一个sayHello抽象方法;
- 定义一个show()方法,该方法需要传入一个Person类型的对象,再调用Perosn类中sayHello()方法;
- 添加main方法,通过匿名内部类的方式来创建Person类的子类对象,调用Person类中的sayHello()方法;
- 调用show()方法。
1 object ClassDemo02 { 2 3 abstract class Person { 4 def sayHello() 5 } 6 7 def show(p:Person) = p.sayHello() 8 def main(args: Array[String]): Unit = { 9 //调用Person类中的sayHello()方法 10 new Person { 11 override def sayHello(): Unit = println("Hello,Scala!") 12 }.sayHello() 13 14 val p:Person = new Person() { //多态,子类指向父类 15 override def sayHello(): Unit = println("Python") 16 } 17 show(p) 18 } 19 }
案例:动物类
需求
- 定义抽象动物类,属性包括:姓名,年龄,行为:跑步和吃饭。
- 定义猫类,重写吃饭方法,并定义独有抓老鼠方法。
- 定义狗类,重写吃饭方法,并定义独有看家方法。
目的
考察:继承、抽象类、类型转换;
步骤
- 定义抽象动物类(Animal),属性:姓名,年龄,行为:跑步,吃饭;
- 定义猫类(Cat)继承自动物类,重写吃饭方法,并定义该类独有的抓老鼠方法;
- 定义狗类(Dog)继承自动物类,重写吃饭方法,并定义该类独有的看家方法。
示例
1 object ClassDemo { 2 3 abstract class Animal{ 4 var name = "" 5 var age = 0 6 7 def run(): Unit = println("run") 8 def eat() 9 } 10 11 class Cat extends Animal{ 12 override def eat(): Unit = println("eat fish") 13 14 def catchMouse(): Unit = println("catch mouse") 15 } 16 17 class Dog extends Animal{ 18 override def eat(): Unit = println("eat meat") 19 20 def catchThief(): Unit = println("catch thief") 21 } 22 23 24 def main(args: Array[String]): Unit = { 25 val animal:Animal = new Cat() 26 if(animal.isInstanceOf[Cat]) { 27 val cat = animal.asInstanceOf[Cat] 28 cat.catchMouse() 29 } else if(animal.isInstanceOf[Dog]) { 30 val dog = animal.asInstanceOf[Dog] 31 dog.catchThief() 32 } else { 33 println("not cat or dog") 34 } 35 } 36 37 }
特质
特质入门
概述
在不影响当前继承体系的情况下,对某些类(或某些对象)的功能进行加强。例如,有猴子类和大象类,都有姓名年龄,以及吃的功能,但部分猴子通过马戏团的训练后,学会了骑独轮车,那独轮车这个功能不能定义到父类(动物类)或猴子类中,而是应该定义到特质中。Scala中特质要用关键字trait修饰。
特点
- 特质可以提高代码的复用性。
- 特质可以提高代码的扩展性和可维护性。
- 类与特质是继承关系,类与类只支持单继承,类与特质之间可以单继承也可以多继承。
- Scala 的特质中可以有普通字段、抽象字段、普通方法、抽象方法。
- 如果特质只有抽象内容也叫瘦接口,如果既有抽象内容又有具体内容叫做富接口。
注意:
- 如果特质中只有抽象内容,这种特质叫:瘦接口;
- 如果特质中既有抽象内容,又有具体内容,叫:富接口;
语法
定义特质
1 trait 特质名称{ 2 3 }
继承特质
1 class 类名 extends 特质1 with 特质2{ 2 3 }
示例1:类继承单个特质
1 object ClassDemo { 2 3 trait Logger{ 4 def log(msg:String) //抽象方法 5 } 6 7 //继承trait 8 class ConsoleLogger extends Logger{ 9 override def log(msg: String): Unit = println(msg) 10 } 11 12 13 def main(args: Array[String]): Unit = { 14 val logger = new ConsoleLogger 15 logger.log("hello scala") 16 } 17 18 }
示例2:类继承多个trait
1 object ClassDemo { 2 3 trait MsgSender{ 4 def send(msg:String) //抽象方法,表示发送消息 5 } 6 7 trait MsgReceiver{ 8 def receive() 9 } 10 11 class MsgWorker extends MsgSender with MsgReceiver{ 12 override def send(msg: String): Unit = println(s"发送消息:$msg") 13 14 override def receive(): Unit = println("接收消息") 15 } 16 17 def main(args: Array[String]): Unit = { 18 val worker = new MsgWorker 19 worker.send("hello") 20 worker.receive() 21 } 22 23 }
示例3:object继承trait
View Code
示例4:演示trait中成员
View Code
对象混入traint
在 Scala 中,类和特质之间无任何继承关系,但通过特定关键字让该类对象具有指定特质中的成员。
语法
1 val/var 对象名 = new 类 with 特质
示例
1 object ClassDemo { 2 3 trait Logger{ 4 def log(): Unit = println("log..") 5 } 6 7 class User{ 8 9 } 10 11 def main(args: Array[String]): Unit = { 12 val user = new User with Logger 13 user.log()//log.. 14 } 15 16 } 17 18 //如果trait中是抽象方法 19 object Class01 { 20 21 trait Logger { 22 def log(msg:String) 23 } 24 25 class User 26 27 def main(args: Array[String]): Unit = { 28 val u = new User with Logger { 29 override def log(msg: String): Unit = println(msg) 30 } 31 u.log("123") 32 } 33 }
使用trait实现适配器模式
设计模式简介
概述
设计模式(Design Pattern)是解决特定问题的一系列套路。并不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。
分类
设计模式一共23中,分为如下3类:
- 创建型:需要创建对象的。常用模式有:单例模式,工厂方法模式;
- 结构型:类,特质之间的关系架构。常用模式:适配器模式,装饰模式;
- 行为型:类(或者特质)能够做什么。常用模式:模板方法模式,职责链模式;
适配器模式
当某个特质中有多个抽象方法,而我们只需要用到某个或某几个方法时不得不将该特质所有抽象方法重写。针对这种情况可以定义一个抽象类继承该特质,重写特质的所有方法,方法体为空。需要使用哪个方法只需要定义类继承抽象类,重写指定方法即可。
结构
1 trait 特质A{ 2 //抽象方法 3 } 4 5 abstract class 类B extends A { //适配器类 6 //重写抽象方法,方法体为空 7 8 } 9 10 class 自定义类C extends 类B { 11 //需要使用哪个方法,就重写哪个方法即可 12 }
示例
1 object ClassDemo { 2 3 trait Play{ 4 def mid() 5 def top() 6 def adc() 7 def jungle() 8 def support() 9 } 10 11 abstract class Player extends Play{ 12 override def mid(): Unit = {} 13 14 override def top(): Unit = {} 15 16 override def adc(): Unit = {} 17 18 override def jungle(): Unit = {} 19 20 override def support(): Unit = {} 21 } 22 23 //新手类 24 class GreenHand extends Player { 25 override def support(): Unit = println("我是辅助") 26 } 27 28 def main(args: Array[String]): Unit = { 29 val player = new GreenHand 30 player.support() 31 } 32 33 }
使用trait实现模板方法模式
使用trait实现职责链模式
trait的构造机制
trait继承class
案例:程序员