Scala面向对象
类和目标
组成结构
• 结构函数: 在创立目标的时分给特点赋值
• 成员变量:
• 成员办法(函数)
• 局部变量
• 代码块
结构器
每个类都有一个主结构器,这个结构器和类界说"交错"在一起类名后边的内容便是主结构器,假如参数列表为空的话,()能够省掉
scala的类有且仅有一个主结构器,要想供给愈加丰厚的结构器,就需求运用辅佐结构器,辅佐结构器是可选的,它们叫做this def this
留意:主结构器会履行类界说中的一切句子
代码示例:
// 类默许有一个无参的主结构函数
class User {
}
val user: User = new User
// 两个参数的主结构函数
class User2(val name: String, age: Int) {
}
val user2 = new User2("jim", 23)
// 运用val润饰的变量默许是成员变量,目标能够拜访
// user2.age // age没有运用val或许var润饰 所以不能被拜访,他不是一个成员变量,而是一个局部变量
//辅佐结构器
class User3 {
var name: String = _
var age: Int = _
// 辅佐结构函数
def this(name: String, age: Int) {
// 结构函数中的首行有必要调用主结构函数或许其他结构函数
this()
this.name = name
this.age = age
}
// 辅佐结构函数
def this(msg: String) = {
// 首行调用一个结构
this("ww", 12)
println(msg)
}
}
val u1 = new User3()
val u2 = new User3("")
val u3 = new User3("lisi", 23)
println(u3.name)
总结:
- 有两类结构器:主结构器,辅佐结构器
- 结构器的界说方位:主结构器和类交错在一起,class Student2(val name: String, var age: Int)
- 辅佐结构器是一个特其他办法,界说在类中 def this(name:String,age:Int,gender:String)
- 辅佐结构器,榜首行有必要调用主结构器(或许其他的辅佐结构器)
- 辅佐结构器的参数不能和主结构器的参数完全共同(参数个数,参数类型,参数次序)
- 能够界说空参的辅佐结构器,可是主结构器的参数有必要进行初始化赋值
- 作用域:辅佐结构器的变量作用域,只在办法中,主结构器的作用域是类中除了成员特点和成员办法之外的一切规模(能够经过反编译检查源码)
结构器的参数阐明
- 主结构函数中运用val 和 var润饰的变量为成员变量
- val 润饰的变量默许只要getter办法 一要初始化
- var 润饰的变量默许有 get和set办法 直接点特点操作 运用 _ 占位能够稍后赋值
- @BeanProperty会生成getMsg setMsg办法
成员办法/函数
在类的成员方位界说的函数或许办法是类的成员的一部分
代码块
在类或许目标中的代码块在实例化的时分会被调用
- 在类成员方位的代码块 结构代码块 每次创立目标都会履行一次
- 在object中成员方位的代码块是静态代码块 只履行一次
- 代码有返回值
object类的底层原理
package com.doit.day01.day02
//假如结构器中的变量,不加var 或许val 那他便是一个局部变量
//加了var 或许val 的话他便是一个私有的成员变量
class Student1(var id: Int, val name: String) {
def sayHello: Unit = {
println(name + ":你好")
}
val sayFunc = () => {
println("hello:" + name)
}
}
object Student2{
var id: Int = 1
//假如在成员变量的方位上给一个_作为占位符,适当所以给他赋了一个默许值啊
var name: String =_
def sayHello: Unit = {
println(name + ":你好")
}
val sayFunc = (x:String) => {
println("hello:" + name + x)
}
}
object Demo01_面向目标 {
def main(args: Array[String]): Unit = {
Student2.sayFunc("a")
val student1: Student1 = new Student1(1, "zhangsan")
println(student1.name)
println(student1.id)
// student1.name = "lisi" 用val 润饰的,不能修正
student1.id = 2
println(student1.id)
student1.sayHello
student1.sayFunc()
println(Student2.name)
}
}
java手写完成:
package com.doit;
public class Person {
public static String getName(){
return Person$.person.getName();
}
public static Integer getAge(){
return Person$.person.getAge();
}
public static void setName(String name ){
Person$.person.setName(name);
}
public static void setAge(Integer age ){
Person$.person.setAge(age);
}
}
class Person$ {
//自己的目标
public static Person$ person ;
//成员变量
private String name;
private int age;
static {
person = new Person$();
}
private Person$() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class Test{
public static void main(String[] args) {
Person person = new Person();
person.setName("张三");
person.setAge(18);
String name1 = person.getName();
Integer age1 = person.getAge();
System.out.println(name1);
System.out.println(age1);
}
}
scala中底层反编译后的代码:
package com.doit.day01.day02;
import java.lang.invoke.SerializedLambda;
import scala.Function1;
import scala.Predef.;
import scala.runtime.BoxedUnit;
public final class Student2$ {
public static Student2$ MODULE$;
private int id;
private String name;
private final Function1 sayFunc;
static {
new Student2$();
}
public int id() {
return this.id;
}
public void id_$eq(final int x$1) {
this.id = x$1;
}
public String name() {
return this.name;
}
public void name_$eq(final String x$1) {
this.name = x$1;
}
public void sayHello() {
.MODULE$.println((new StringBuilder(3)).append(this.name()).append(":你好").toString());
}
public Function1 sayFunc() {
return this.sayFunc;
}
// $FF: synthetic method
public static final void $anonfun$sayFunc$1(final String x) {
.MODULE$.println((new StringBuilder(6)).append("hello:").append(MODULE$.name()).append(x).toString());
}
private Student2$() {
MODULE$ = this;
this.id = 1;
this.sayFunc = (x) -> {
$anonfun$sayFunc$1(x);
return BoxedUnit.UNIT;
};
}
// $FF: synthetic method
private static Object $deserializeLambda$(SerializedLambda var0) {
return var0.lambdaDeserialize<invokedynamic>(var0);
}
}
//decompiled from Student2.class
package com.doit.day01.day02;
import scala.Function1;
import scala.reflect.ScalaSignature;
@ScalaSignature(
bytes = "\u0006\u0001!;Q\u0001D\u0007\t\u0002Y1Q\u0001G\u0007\t\u0002eAQ\u0001I\u0001\u0005\u0002\u0005BqAI\u0001A\u0002\u0013\u00051\u0005C\u0004(\u0003\u0001\u0007I\u0011\u0001\u0015\t\r9\n\u0001\u0015)\u0003%\u0011%y\u0013\u00011AA\u0002\u0013\u0005\u0001\u0007C\u0005=\u0003\u0001\u0007\t\u0019!C\u0001{!Iq(\u0001a\u0001\u0002\u0003\u0006K!\r\u0005\u0006\u0001\u0006!\t!\u0011\u0005\b\u0005\u0006\u0011\r\u0011\"\u0001D\u0011\u00199\u0015\u0001)A\u0005\t\u0006A1\u000b^;eK:$(G\u0003\u0002\u000f\u001f\u0005)A-Y=1e)\u0011\u0001#E\u0001\u0006I\u0006L\b'\r\u0006\u0003%M\tA\u0001Z8ji*\tA#A\u0002d_6\u001c\u0001\u0001\u0005\u0002\u0018\u00035\tQB\u0001\u0005TiV$WM\u001c;3'\t\t!\u0004\u0005\u0002\u001c=5\tADC\u0001\u001e\u0003\u0015\u00198-\u00197b\u0013\tyBD\u0001\u0004B]f\u0014VMZ\u0001\u0007y%t\u0017\u000e\u001e \u0015\u0003Y\t!!\u001b3\u0016\u0003\u0011\u0002\"aG\u0013\n\u0005\u0019b\"aA%oi\u00061\u0011\u000eZ0%KF$\"!\u000b\u0017\u0011\u0005mQ\u0013BA\u0016\u001d\u0005\u0011)f.\u001b;\t\u000f5\"\u0011\u0011!a\u0001I\u0005\u0019\u0001\u0010J\u0019\u0002\u0007%$\u0007%\u0001\u0003oC6,W#A\u0019\u0011\u0005IJdBA\u001a8!\t!D$D\u00016\u0015\t1T#\u0001\u0004=e>|GOP\u0005\u0003qq\ta\u0001\u0015:fI\u00164\u0017B\u0001\u001e<\u0005\u0019\u0019FO]5oO*\u0011\u0001\bH\u0001\t]\u0006lWm\u0018\u0013fcR\u0011\u0011F\u0010\u0005\b[\u001d\t\t\u00111\u00012\u0003\u0015q\u0017-\\3!\u0003!\u0019\u0018-\u001f%fY2|W#A\u0015\u0002\u000fM\f\u0017PR;oGV\tA\t\u0005\u0003\u001c\u000bFJ\u0013B\u0001$\u001d\u0005%1UO\\2uS>t\u0017'\u0001\u0005tCf4UO\\2!\u0001"
)
public final class Student2 {
public static Function1 sayFunc() {
return Student2$.MODULE$.sayFunc();
}
public static void sayHello() {
Student2$.MODULE$.sayHello();
}
public static void name_$eq(final String x$1) {
Student2$.MODULE$.name_$eq(var0);
}
public static String name() {
return Student2$.MODULE$.name();
}
public static void id_$eq(final int x$1) {
Student2$.MODULE$.id_$eq(var0);
}
public static int id() {
return Student2$.MODULE$.id();
}
}
伴生类和伴生目标
条件 1:在同一个源文件中, 条件 2:目标名和类名相同
//类名和object的称号共同
//类是目标的伴生类
//目标是类的伴生目标
class Demo6(val name: String) {
}
object Demo6 {
}
条件 2:伴生目标和伴生类之间能够相互拜访互相的私有特点和私有办法
package com.doit.day01.day02
/**
* 伴生目标的用处:
* 1.能够将静态的成员变量和一般成员变量别离声明
* 2.伴生目标自己内部界说了一个apply办法,能够简化创立目标(类的实例结构)
* 3.伴生目标自己界说了一个unapply办法,能够用于形式匹配
*/
class Car(var brand: String, var price: Double) {
def sayHello(): Unit ={
println("hello")
}
private val color: String = Car.color
Car.start()
}
object Car {
var color :String = "red"
def start(): Unit ={
println("轿车启动了,嗡~~~~~~~~")
}
}
object Demo02_伴生目标 {
def main(args: Array[String]): Unit = {
val car: Car = new Car("华为", 9.9)
println(car.brand)
println(car.price)
car.sayHello()
Car.start()
}
}
伴生目标的底层原理:
//decompiled from Car.class
package com.doit.day01.day02;
import scala.Predef.;
import scala.reflect.ScalaSignature;
@ScalaSignature(
bytes = "\u0006\u0001E3A\u0001E\t\u00015!A\u0011\u0005\u0001BA\u0002\u0013\u0005!\u0005\u0003\u0005/\u0001\t\u0005\r\u0011\"\u00010\u0011!)\u0004A!A!B\u0013\u0019\u0003\u0002\u0003\u001c\u0001\u0005\u0003\u0007I\u0011A\u001c\t\u0011m\u0002!\u00111A\u0005\u0002qB\u0001B\u0010\u0001\u0003\u0002\u0003\u0006K\u0001\u000f\u0005\u0006\u007f\u0001!\t\u0001\u0011\u0005\u0006\u000b\u0002!\tAR\u0004\u0006\u000fFA\t\u0001\u0013\u0004\u0006!EA\t!\u0013\u0005\u0006\u007f)!\tA\u0013\u0005\b\u0017*\u0001\r\u0011\"\u0001#\u0011\u001da%\u00021A\u0005\u00025Caa\u0014\u0006!B\u0013\u0019\u0003\"\u0002)\u000b\t\u00031%aA\"be*\u0011!cE\u0001\u0006I\u0006L\bG\r\u0006\u0003)U\tQ\u0001Z1zaER!AF\f\u0002\t\u0011|\u0017\u000e\u001e\u0006\u00021\u0005\u00191m\\7\u0004\u0001M\u0011\u0001a\u0007\t\u00039}i\u0011!\b\u0006\u0002=\u0005)1oY1mC&\u0011\u0001%\b\u0002\u0007\u0003:L(+\u001a4\u0002\u000b\t\u0014\u0018M\u001c3\u0016\u0003\r\u0002\"\u0001J\u0016\u000f\u0005\u0015J\u0003C\u0001\u0014\u001e\u001b\u00059#B\u0001\u0015\u001a\u0003\u0019a$o\\8u}%\u0011!&H\u0001\u0007!J,G-\u001a4\n\u00051j#AB*ue&twM\u0003\u0002+;\u0005I!M]1oI~#S-\u001d\u000b\u0003aM\u0002\"\u0001H\u0019\n\u0005Ij\"\u0001B+oSRDq\u0001\u000e\u0002\u0002\u0002\u0003\u00071%A\u0002yIE\naA\u0019:b]\u0012\u0004\u0013!\u00029sS\u000e,W#\u0001\u001d\u0011\u0005qI\u0014B\u0001\u001e\u001e\u0005\u0019!u.\u001e2mK\u0006I\u0001O]5dK~#S-\u001d\u000b\u0003auBq\u0001N\u0003\u0002\u0002\u0003\u0007\u0001(\u0001\u0004qe&\u001cW\rI\u0001\u0007y%t\u0017\u000e\u001e \u0015\u0007\u0005\u001bE\t\u0005\u0002C\u00015\t\u0011\u0003C\u0003\"\u000f\u0001\u00071\u0005C\u00037\u000f\u0001\u0007\u0001(\u0001\u0005tCfDU\r\u001c7p)\u0005\u0001\u0014aA\"beB\u0011!IC\n\u0003\u0015m!\u0012\u0001S\u0001\u0006G>dwN]\u0001\nG>dwN]0%KF$\"\u0001\r(\t\u000fQj\u0011\u0011!a\u0001G\u000511m\u001c7pe\u0002\nQa\u001d;beR\u0004"
)
public class Car {
private String brand;
private double price;
public static void start() {
Car$.MODULE$.start();
}
public static void color_$eq(final String x$1) {
Car$.MODULE$.color_$eq(var0);
}
public static String color() {
return Car$.MODULE$.color();
}
public String brand() {
return this.brand;
}
public void brand_$eq(final String x$1) {
this.brand = x$1;
}
public double price() {
return this.price;
}
public void price_$eq(final double x$1) {
this.price = x$1;
}
public void sayHello() {
.MODULE$.println("hello");
}
public Car(final String brand, final double price) {
this.brand = brand;
this.price = price;
super();
}
}
//decompiled from Car$.class
package com.doit.day01.day02;
import scala.Predef.;
public final class Car$ {
public static Car$ MODULE$;
private String color;
static {
new Car$();
}
public String color() {
return this.color;
}
public void color_$eq(final String x$1) {
this.color = x$1;
}
public void start() {
.MODULE$.println("轿车启动了,嗡~~~~~~~~");
}
private Car$() {
MODULE$ = this;
this.color = "red";
}
}
图示:
伴生目标用处:
- 能够将静态的成员变量和一般成员变量别离声明(class中没办法添加静态成员,需求经过object类来添加)
- 伴生目标自己内部界说了一个apply办法,能够简化创立目标(类的实例结构)
- 伴生目标自己界说了一个unapply办法,能够用于形式匹配
apply办法
运用此办法时,能够在main函数中不经过new来创立一个目标,即能够不必专门的一次一次地进行实例化,加载创立目标的这个类的时分,会主动调用apply这个办法,相似Java中的static静态块。
- 经过伴生目标的 apply 办法,完成不运用 new 办法创立目标。
- apply 办法能够重载。
- Scala 中 obj(arg)的句子实践是在调用该目标的 apply 办法,即 obj.apply(arg)。用以一致面向目标编程和函数式编程的风格。
- 当运用 new 关键字构建目标时,调用的其实是类的结构办法,当直接运用类名构建目标时,调用的其实是伴生目标的 apply 办法。
object Test {
def main(args: Array[String]): Unit = {
//(1)经过伴生目标的 apply 办法,完成不运用 new 关键字创立目标。
val p1 = Person()
println("p1.name=" + p1.name)
val p2 = Person("bobo")
println("p2.name=" + p2.name)
}
}
//(2)假如想让主结构器变成私有的,能够在()之前加上 private
class Person private(cName: String) {
var name: String = cName
}
object Person {
def apply(): Person = {
println("apply 空参被调用")
new Person("xx")
}
def apply(name: String): Person = {
println("apply 有参被调用")
new Person(name)
}
}
权限润饰符
在 Java 中,拜访权限分为:public,private,protected 和默许。在 Scala 中,你能够经过相似的润饰符到达相同的作用。可是运用上有差异。
(1)Scala 中特点和办法的默许拜访权限为 public,但 Scala 中无 public 关键字。
(2)private 为私有权限,只在类的内部和伴生目标中可用。
(3)protected 为受维护权限,Scala 中受维护权限比 Java 中更严厉,同类、子类能够拜访,同包无法拜访。
(4)private[包名]添加包拜访权限,包名下的其他类也能够运用
代码演示:
class Person {
private var name: String = "bobo"
protected var age: Int = 18
private[test] var sex: String = "男"
def say(): Unit = {
println(name)
}
}
object Person {
def main(args: Array[String]): Unit = {
val person = new Person
person.say()
println(person.name)
println(person.age)
}
}
class Teacher extends Person {
def test(): Unit = {
this.age
this.sex
}
}
class Animal {
def test: Unit = {
new Person().sex
}
}
特质和笼统类
特质
Trait(特质)适当于 java 的接口。比接口功用更强壮。特质中能够界说特点和笼统办法和办法的完成。
Scala 的类只能够承继单一父类,可是能够完成(承继,混入)多个特质(Trait),运用的关键字是 with 和 extends
留意,特质不能有主结构函数
根本语法
trait 特质名 {
trait 主体
}
怎么运用特质:
没有父类:class 类名 extends 特质 1 with 特质 2 with 特质 3 …
有父类:class 类名 extends 父类 with 特质 1 with 特质 2 with 特质 3…
代码演示:
trait PersonTrait {
// 声明特点
var name:String = _
// 声明办法
def eat():Unit={
}
// 笼统特点
var age:Int
// 笼统办法
def say():Unit
}
特质的实质便是笼统类+接口
特质的动态混入
1.创立目标时混入 trait,而无需使类混入该 trait
2.假如混入的 trait 中有未完成的办法,则需求完成
代码演示:
trait PersonTrait {
//(1)特质能够一起具有笼统办法和详细办法
// 声明特点
var name: String = _
// 笼统特点
var age: Int
// 声明办法
def eat(): Unit = {
println("eat")
}
// 笼统办法
def say(): Unit
}
trait SexTrait {
var sex: String
}
//(2)一个类能够完成/承继多个特质
//(3)一切的 Java 接口都能够作为 Scala 特质运用
class Teacher extends PersonTrait with java.io.Serializable {
override def say(): Unit = {
println("say")
}
override var age: Int = _
}
object TestTrait {
def main(args: Array[String]): Unit = {
val teacher = new Teacher
teacher.say()
teacher.eat()
//(4)动态混入:可灵敏的扩展类的功用
val t2 = new Teacher with SexTrait {
override var sex: String = "男"
}
//调用混入 trait 的特点
println(t2.sex)
}
}
笼统类
在 Scala 中, 运用 abstract 润饰的类称为笼统类. 在笼统类中能够界说特点、未完成的办法(笼统办法)和详细完成的办法。 含有笼统办法的类便是笼统类
- 笼统类中的特点
- 笼统办法
- 详细完成的办法
- 类的单承继
示例:
/*
* abstract 润饰的类是一个笼统类
* */
abstract class Animal {
println("Animal's constructor ....")
// 界说一个 name 特点
val name: String = "animal"
// 没有任何完成的办法
def sleep()
// 带有详细的完成的办法
def eat(f: String): Unit = {
println(s"$f")
}
}
笼统类的承继和重写
- 假如父类为笼统类,那么子类要么也是笼统类,要么就需求重写父类中的一切的笼统办法和笼统的成员变量
- 重写非笼统办法需求用 override 润饰,重写笼统办法则能够不加 override。
- 子类中调用父类的办法运用 super 关键字,在子类重写了父类的办法后,假如不加super,直接写办法名调用的便是子类重写后的,假如加了,调用的仍是父类的
- 子类对笼统特点进行完成,父类笼统特点能够用 var 润饰;子类对非笼统特点重写,父类非笼统特点只支撑 val 类型,而不支撑 var(var润饰详细办法和变量欠好重写)
由于 var 润饰的为可变变量,子类承继之后就能够直接运用,没有必要重写
样例类
运用case润饰的类便是样例类(封装数据,形式匹配)
- 结构器中的参数默许是val润饰的[成员,赋值1次]
- 样例类会主动创立伴生目标, 一起在里面完成;的apply和unapply办法 ,创立目标的时分不必new
- 很好的支撑匹配形式
- 默许完成了自己的toString , hashCode , copy , equals,序列化办法
界说一个样例类:
case class Person(var name:String , var age:Int){}
//假如类中没有其他需求界说的,能够不写大括号
反编译之后的成果:
//decompiled from Person$.class
package com.doit.day01.day02;
import scala.Option;
import scala.Serializable;
import scala.Some;
import scala.Tuple2;
import scala.None.;
import scala.runtime.AbstractFunction2;
import scala.runtime.BoxesRunTime;
public final class Person$ extends AbstractFunction2 implements Serializable {
public static Person$ MODULE$;
static {
new Person$();
}
public final String toString() {
return "Person";
}
public Person apply(final String name, final int age) {
return new Person(name, age);
}
public Option unapply(final Person x$0) {
return (Option)(x$0 == null ? .MODULE$ : new Some(new Tuple2(x$0.name(), BoxesRunTime.boxToInteger(x$0.age()))));
}
private Object readResolve() {
return MODULE$;
}
// $FF: synthetic method
// $FF: bridge method
public Object apply(final Object v1, final Object v2) {
return this.apply((String)v1, BoxesRunTime.unboxToInt(v2));
}
private Person$() {
MODULE$ = this;
}
}
//decompiled from Person.class
package com.doit.day01.day02;
import scala.Function1;
import scala.Option;
import scala.Product;
import scala.Serializable;
import scala.collection.Iterator;
import scala.reflect.ScalaSignature;
import scala.runtime.BoxesRunTime;
import scala.runtime.Statics;
import scala.runtime.ScalaRunTime.;
@ScalaSignature(
bytes = "\u0006\u0001\u0005Uc\u0001\u0002\u000e\u001c\u0001\u0012B\u0001\"\r\u0001\u0003\u0012\u0004%\tA\r\u0005\t}\u0001\u0011\t\u0019!C\u0001\u007f!AQ\t\u0001B\tB\u0003&1\u0007\u0003\u0005G\u0001\tE\r\u0011\"\u0001H\u0011!Y\u0005A!a\u0001\n\u0003a\u0005\u0002\u0003(\u0001\u0005#\u0005\u000b\u0015\u0002%\t\u000b=\u0003A\u0011\u0001)\t\u000fU\u0003\u0011\u0011!C\u0001-\"9\u0011\fAI\u0001\n\u0003Q\u0006bB3\u0001#\u0003%\tA\u001a\u0005\bQ\u0002\t\t\u0011\"\u0011j\u0011\u001d\t\b!!A\u0005\u0002\u001dCqA\u001d\u0001\u0002\u0002\u0013\u00051\u000fC\u0004y\u0001\u0005\u0005I\u0011I=\t\u0013\u0005\u0005\u0001!!A\u0005\u0002\u0005\r\u0001\"CA\u0007\u0001\u0005\u0005I\u0011IA\b\u0011%\t\t\u0002AA\u0001\n\u0003\n\u0019\u0002C\u0005\u0002\u0016\u0001\t\t\u0011\"\u0011\u0002\u0018\u001dI\u00111D\u000e\u0002\u0002#\u0005\u0011Q\u0004\u0004\t5m\t\t\u0011#\u0001\u0002 !1q\n\u0006C\u0001\u0003[A\u0011\"!\u0005\u0015\u0003\u0003%)%a\u0005\t\u0013\u0005=B#!A\u0005\u0002\u0006E\u0002\"CA\u001c)\u0005\u0005I\u0011QA\u001d\u0011%\tY\u0005FA\u0001\n\u0013\tiE\u0001\u0004QKJ\u001cxN\u001c\u0006\u00039u\tQ\u0001Z1zaIR!AH\u0010\u0002\u000b\u0011\f\u0017\u0010M\u0019\u000b\u0005\u0001\n\u0013\u0001\u00023pSRT\u0011AI\u0001\u0004G>l7\u0001A\n\u0005\u0001\u0015Zc\u0006\u0005\u0002'S5\tqEC\u0001)\u0003\u0015\u00198-\u00197b\u0013\tQsE\u0001\u0004B]f\u0014VM\u001a\t\u0003M1J!!L\u0014\u0003\u000fA\u0013x\u000eZ;diB\u0011aeL\u0005\u0003a\u001d\u0012AbU3sS\u0006d\u0017N_1cY\u0016\fAA\\1nKV\t1\u0007\u0005\u00025w9\u0011Q'\u000f\t\u0003m\u001dj\u0011a\u000e\u0006\u0003q\r\na\u0001\u0010:p_Rt\u0014B\u0001\u001e(\u0003\u0019\u0001&/\u001a3fM&\u0011A(\u0010\u0002\u0007'R\u0014\u0018N\\4\u000b\u0005i:\u0013\u0001\u00038b[\u0016|F%Z9\u0015\u0005\u0001\u001b\u0005C\u0001\u0014B\u0013\t\u