1:类
1.1:定义类:
scala是支持面向对象的,也有类和对象的概念。 说明
var name:String = _, _表示使用默认值进行初始化 val变量不能使用_来进行初始化,因为val是不可变的,所以必须手动指定一个默认值 main方法必须要放在一个scala的object(单例对象)中才能执行
class Customer {
var name: String = _
var sex: String = _
val registerDate: Date = new Date
def sayHi ( msg: String) = {
println ( msg)
}
}
object Main {
def main ( args: Array[ String] ) : Unit = {
val customer = new Customer
customer. name = "张三"
customer. sex = "男"
println ( s"姓名: ${customer.name}, 性别:${customer.sex}, 注册时间: ${customer.registerDate}" )
customer. sayHi ( "你好!" )
}
}
1.2:构造器:
class 类名( var/ val 参数名: 类型 = 默认值, var/ val 参数名: 类型 = 默认值) {
}
def this ( 参数名: 类型, 参数名: 类型) {
. . .
}
class Student ( val name: String, val age: Int) {
val address: String= "beijing"
def this ( name: String) {
this ( name, 20 )
}
def this ( age: Int) {
this ( "年龄" , age)
}
}
2:对象
2.1:scala中的object
scala中是没有Java中的静态成员的。如果将来我们需要用到static变量、static方法,就要用到scala中的单例对象object 定义object:定义单例对象和定义类很像,就是把class换成object 说明
使用object 单例对象名定义一个单例对象,可以用object作为工具类或者存放常量 在单例对象中定义的变量,类似于Java中的static成员变量 在单例对象中定义的方法,类似于Java中的static方法 object单例对象的构造代码可以直接写在花括号中 调用单例对象的方法,直接使用单例对象名.方法名,访问单例对象的成员变量也是使用单例对象名.变量名 单例对象只能有一个无参的主构造器,不能添加其他参数 示例
object DateUtils {
val simpleDateFormat = new SimpleDateFormat ( "yyyy-MM-dd HH:mm" )
println ( "构造代码" )
def format ( date: Date) = simpleDateFormat. format ( date)
def main ( args: Array[ String] ) : Unit = {
println { DateUtils. format ( new Date ( ) ) } ;
}
}
2.2:scala中的伴生对象
在同一个scala文件,有一个class和object具有同样的名字
,那么就称这个object是class的伴生对象,class是object的伴生类,伴生类和伴生对象的最大特点是,可以相互访问 说明
伴生类和伴生对象的名字必须是一样的 伴生类和伴生对象需要在一个scala源文件中 伴生类和伴生对象可以互相访问private的属性 示例
class ClassObject {
val id = 1
private var name = "itcast"
def printName ( ) : Unit = {
println ( ClassObject. CONSTANT + name )
}
}
object ClassObject{
private val CONSTANT = "您好 : "
def main ( args: Array[ String] ) {
val p = new ClassObject
p. name = "123"
p. printName ( )
}
}
2.3:scala中object的apply方法
伴生对象的apply方法用来快速地创建一个伴生类的对象 说明
当遇到类名(参数1, 参数2…)会自动调用apply方法,在apply方法中来创建对象 定义apply时,如果参数列表是空,也不能省略括号(),否则引用的是伴生对象 示例
class Person ( var name: String, var age: Int) {
override def toString = s"Person($name, $age)"
}
object Person {
def apply ( name: String, age: Int) : Person = new Person ( name, age)
def apply ( name: String) : Person = new Person ( name, 20 )
def apply ( age: Int) : Person = new Person ( "年龄" , age)
def apply ( ) : Person = new Person ( "年龄" , 20 )
}
object Main2 {
def main ( args: Array[ String] ) : Unit = {
val p1 = Person ( "张三" , 20 )
val p2 = Person ( "李四" )
val p3 = Person ( 100 )
val p4 = Person ( )
println ( p1)
println ( p2)
println ( p3)
println ( p4)
}
}
2.4: scala中object的main方法
scala和Java一样,如果要运行一个程序,必须有一个main方法,而在Java中main方法是静态的,而在scala中没有静态方法 在scala中,这个main方法必须放在一个object中
object Main1{
def main ( args: Array[ String] ) = {
println ( "hello, scala" )
}
}
也可以继承自 Trait(特质),然后将需要编写在main方法中的代码,写在object的构造方法体内。其本质是调用了Trait这个特质中的main方法
3:继承
3.1 继承extends
class Student extends Persion {
}
3.2 override和super
可以使用override关键字来重写一个val字段 可以使用super关键字访问父类的成员
class Persion {
val name = 'superName'
def getName = name
}
class Student extends Persion {
override val name String= "child"
override def getName: String = "hi ," + super . getName
}
3.3:isInstanceOf和asInstanceOf
isInstanceOf:判断对象是否为指定的对象 asInstanceOf:将对象转换成指定类型
java Scala 判断对象是否为C类型 obj instanceof C obj.isInstanceof[C] 将对象强转成C类型 (C)obj obj.asInstanceof[C] 获取类型为T的class类型 C.class classOf[C]
3.4:getClass和classOf
isInstanceOf 只能判断出对象是否为指定类及其子类的对象,而不能精确判断出,对象就是指定的对象。如果要求精确地判断出对象就是指定类的对象,那么只能使用getClass和classOf
对象.getClass可以精确的获取对象的类型 classOf[类型] 可以精确获取类型 使用==操作符就可以直接比较
3.5:访问修饰符
java中的访问控制,通样适用于scala,可以在成员前面添加private/protected关键字来控制成员的课件行。但是在scala中没有public关键,任何没有被private/protected修饰的成员变量都是公共的
private[this]
被修饰的成员只是在当前类中被访问。可以理解为只能通过this.来访问 protected[this]
被修饰的成员只是在当前类和当前类子类中被访问。可以理解为通过this.来访问或者子类通过this.访问
3.6:调用父类的constructor
实例化子类对象,必须调用父类的构造器
,在scala中,只能在子类的主构造器中调用父类结构器示例
class Persion ( var name: String) {
print ( "name:" + name)
}
class student ( name: String, var clazz: String) extends Persion ( name)
3.7:抽象类
如果类的某个成员在当前类的定义是不完整的,它就是一个抽象类
两种情况
没有方法体的方法称为抽象方法
,没有初始化的变量称为抽象字段
。定义抽象类和java一样,在类前面加上abstract
关键字 示例
abstract class Persion ( val name: string) {
def say: String
val address: String
}
3.8:匿名内部类
匿名内部类是没有名字的子类,直接用来穿件实例对象。
abstract calss Persion{
def say: unit
}
object Test{
def main ( args: Array[ String] ) : Unit = {
val p1= new Persion {
override defsay: unit= println ( "匿名内部类" )
}
p1. say
}
}
4: trait特质
4.1 作为接口使用
使用 extends来继承trait 如果要继承多个trait,则使用with
关键字 示例
trait Persion {
def say ( msg: String)
}
class Student extends Persion {
override def log ( msg: String) : Unit = print ( msg)
}
4.2:定义具体的方法
trait Persion {
def say ( msg: String) = print ( msg)
}
4.3:定义具体的方法和抽象方法
在trait 中,可以混合使用具体方法和抽象方法 使用具体方法依赖于抽象方法,而抽象方法可以放到继承trait 的子类中实现,这种设计方式也称为模板模式
示例
trait Logs {
def log ( msg: String)
def info ( msg: String) = log ( "INFO" + msg: String)
def warn ( msg: String) = log ( "WARN" + msg: String)
def error ( msg: String) = log ( "REEOR" + msg: String)
}
class ConsoleLogs extends Logs {
override def log ( msg: String) : Unit= print ( msg)
}
4.4:定义具体字段和抽象字段
在trait 中可以定义具体字段和抽象字段 继承trait 的子类自动拥有trait 中定义的字段,字段直接被添加到子类中 示例
trait logs {
val sdf = new SimpleDateFormat ( "yyyy-MM-dd HH:mm" )
val Info = "信息:" + sdf. format ( new Date )
val TYPE: String
def log ( msg: string)
}
class ConsoleLog extends logs {
override val TYPE: String = 'kongzhitai'
override def ( msg: String) : Unit= print ( s"$TYPE$Info $msg" )
}
4.5:实例对象混入trait
trait 还可以混入到实例对象中,给对象实例增加额外的行为,只有混入了trait 的对象才具有trait中的方法,其他的类对象不具有trait 中的行为 使用with将trait 混入到实例对象中
trait logs {
def log ( msg: string) = print ( msg)
}
class UserService
object Test{
def main ( args: Array[ String] ) : Unit = {
var UserService = new UserService with logs
UserService. log ( "hello" )
}
}
4.5:trait 调用链
责任链模式 - 示例 类继承trait 后,可以依次调用多个trait 中的同一个方法,只要trait 中的同一个方法在最有都依次执行super关键字即可。类中调用多个trait 中都有这个方法时,首先会从最右边的trait 方法开始执行,然后依次往左执行,形成一个调用链
trait Handler {
def handel ( data: String) {
print ( "处理数据" )
}
}
trait DataValid extents Handler{
override def handel ( data: String) {
print ( "验证数据" )
super . handel ( data)
}
}
trait SignatureValid extents Handler{
override def handel ( data: String) {
print ( "签名检查" )
super . handel ( data)
}
}
class PaymentService extents DataValid with SignatureValid {
def pay ( data: String) {
print ( "支付数据" )
this . handel ( data)
}
}
4.6:trait 构造机制
trait也有构造代码,单和类不一样,trait不能有构造器参数 每一个trait只有一个无参的构造器 一个类继承另一个类、以及多个trait,点创建类的实例对象时,构造顺序如下:
1):执行父类的构造器 2):从左到右依次执行trait的构造器 3):如果trait有父trait,先构造父trait,如果多个trait有同样的父trait,只初始化一次 4):执行子类构造器
4.7:trait 继承class
trait也可以继承class
继承的class会成为所有trait子类的超级父类