Scala进阶
来源:互联网 发布:非主流 知乎 编辑:程序博客网 时间:2024/06/06 00:46
Scala进阶
定义类
class User{ //类成员必须初使化, var name:String=null @BeanProperty var alias:String="caspar" private[this] var age=null //println将作为主构建器中的一部分,在创建对象时被执行 println("constructing user ........") //重写toString()方法 override def toString()= name + ":"+ alias}//通过继承App,定义一个应用程序对象//扩展App后,程序可以直接运行,而不需要自己定义main方法,代码更简洁object UserTest extends App{ var user = new User() user.name="caspar" //直接修改,但其实调用的是p.name_=("jonh") user.alias_=("csp") println(user)}
*Scala会默认生成name(),name_=(.)和构造函数()
*name()对应java中的getName()方法
*name_=()对应java中的setName()方法
*定义的是公有成员,但生成的字节码中是以私有方式实现的,生成的getter,setter方法是公有的
*定义私有成员,其getter,setter也是私有的
*如果将成员域定义为private[this],则不会生成getter,setter方法
*private[this]只能由该类创建的对象本身能访问到,因此它定义的类成员也称为对象私有成员
*如需要像java中一样自动产生getter,setter方法,需要引用scala.reflect.BeanProperty,采用注解的方式修饰变量
*当主构造器的参数不用var或val修饰的时候,参数会生成类的私有val成员,并且不会产生getter和setter方法
自定义getter和setter方法
def name=name def name_=(name:String){ this.name=name}
定义类的同时定义主构造器
class User(val name:String,val age:Int){ override def toString: String = name +":"+ age}object Test extends App{ val user = new User("caspar",27) println(user)}
主构建器带默认参数
class User(val name:String="",val age:Int=28){...}
主构造器中参数带访问控制符
class User(val name:String,private val age:Int=19){ override def toString: String = name +":"+ age println("age"+age)}object Test extends App{ val user = new User("caspar",12) //user.age //error inaccessible println(user)}
类名后面紧跟private关键字可以将主构建器设为私有,不允许外部使用
class User private(var name:String,var age:Int){...}
*如果禁用掉了主构建器,则必须使用辅助构造函数来创建对象
*辅助构建器的名称为this,java中的辅助构造函数与类名相同,这常常会导致修改类名时出现不少问题,scala语言避免了这样的问题
*调用辅助构造函数时,必须先调用主构造函数或其它已经定义好的构造函数
只有辅助构造函数的类
class User(){ //类成员 private var name:String=null private var age:Int=18 private var sex:Int=0 //辅助构造器 def this(name:String){ this() this.name=name } def this(name:String,age:Int){ this(name) this.age=age } def this(name:String,age:Int,sex:Int){ this(name,age) this.sex=sex } override def toString: String = name+":"+age+":"+sex}object Test extends App{ val user1 = new User("caspar",12,1) val user2 = new User("caspar",12) val user3 = new User("caspar") println(user1) println(user2) println(user3)}
带有主构建函数和辅助构建函数的类
class User(var name:String,var age:Int){ //类成员 private var sex:Int=0 def this(name:String,age:Int,sex:Int){ this(name,age) this.sex=sex } override def toString: String = name +":"+age+":"+sex}object Test extends App{ val user1 = new User("caspar",12,1) val user2 = new User("caspar",12) println(user1) println(user2)}
Abstract类
抽象类是一种不能被实例化的类,抽象类中包括了未实现的抽象方法,这些方法由子类去扩展自己的实现
子类继承抽象类,抽象类中的方法必须有实现,否则子类也必须定义为抽象类
抽象类也可以直接new一个匿名类对象,在该匿名类对象中对方法加以实现
scala中的抽象类定义
abstract class User { def login:Unit}
除抽象方法外,抽象类中还可以有抽象字段:
abstract class User { def login:Unit //抽象字段,一般类中定义字段必须初始化,而抽象类中则没有这要求 var age:Int var name:String}//通过主构造器对name参数进行了初始化class Waiter(var name:String) extends User{ override def login: Unit = { println("waiter "+name+" is logined") } override var age: Int = _}class Customer extends User{ //对父类中的方法进行实现,注意这里面可以不加override关键字 def login: Unit = { println("Customer "+name+" is logined") } override var age: Int = 0 override var name: String = null}object Test extends App{ val user = new Customer() user.name = "caspar" user.login val waiter = new Waiter("caspar") waiter.login //下面的代码定义了一个匿名类,并且进行了实例化 //直接new User,后面跟的是类的内容 //User是一个抽象类,它是不能被实例化的 //这里能够直接new操作是因为我们扩展了User类,这个类是匿名的,只能使用一次 var somebody = new User { override def login: Unit = { println("User "+name+" is logined") } override var name: String = _ override var age: Int = _ } somebody.name="caspar" somebody.login }
伴生对象与伴生类
class User { def print:Unit ={ UserTest.num+=1 println( UserTest.num+".\tname:"+name+"\tage:"+age ) } var age:Int = _ var name:String = _}object UserTest extends App{ var num = 0 var user = new User() user.name="caspar" user.age=29 user.print user.print user.print}
object UserTest被称为class User的伴生对象,而class User被称为object Usertest的伴生类
内部类
*内部类可以像类的其它成员一样访问外部类的私有成员 *外部类不能访问内部类的成员域,但内部类可以直接访问外部类成员域,即使private私有的
class User { def print:Unit ={ println( "name:"+name+"\tage:"+age ) } var name:String = _ private var pwd:String = "password" var age:Int=18 private[this] def info: String = "name:"+name+"\tage:"+age class SocialAccount(var google:String){ var qq:String = _ var email:String = _ var facebook:String= _ //内部的类可以直接访问外部类的成员变量和成员方法,即使是private override def toString: String = info+"\tpwd:"+pwd+"\tqq:"+qq+"\temail:"+email+"\tfacebook:"+facebook+"\tgoogle"+google def print:Unit ={ println(this) } }}object Test extends App{ val user = new User user.name= "caspar" user.age=19 user.print var a = new user.SocialAccount("google account") a.facebook="facebook account" a.qq="qq account" a.email="test@test.com" a.print}
类的继承extends及多态
*“多态”(Polymorphic)也叫“动态绑定”(Dynamic Binding)、“迟绑定”(Late Binding),指“在执行期间(而非编译期间)判断所引用对象的实际类型,根据其实际类型调用其相应的方法。”即指子类的引用可以赋给父类,程序在运行时根据实际类型调用对应的方法
*override方法重写指的是当子类继承父类的时候,子类重写父类的方法,方法重写是实现多态和动态绑定的关键
*scala中的方法重写同java一样,也是利用override关键字标识重写父类的算法
类的继承
class User { def print:Unit ={ println( "name:"+name+"\tage:"+age ) } var name:String = _ private var pwd:String = "password" protected var phone:String = "12345678900" var age:Int=18}class Customer(var vip:Boolean) extends User{ //子类可以访问父类的protected属性和方法,但不能访问private属性和方法 //重写了自己的实现 override def print: Unit = println("Customer name:"+name+"\tCustomer age:"+age+"\tvip:"+vip+"\tphone:"+phone)}object Test extends App{ //User类的引用可以指向User类的任何子类 val c:User = new Customer(false) c.name= "caspar" c.age=19 //c.phone =10 这里不能访问到protected phone c.print //程序会根据实际类型调用对应的不同子类中的print()方法}
构造函数执行顺序
class User { println("第一行输出:User.....") def print:Unit ={ println( "name:"+name+"\tage:"+age ) } var name:String = _ private var pwd:String = "password" protected var phone:String = "12345678900" var age:Int=18}class Customer(var vip:Boolean) extends User{ var qq:String = _ var email:String = _ def this(vip:Boolean,qq:String,email:String){ this(vip) this.qq = qq this.email = email println("第二行输出:Customer this(...)...") } println("第三行输出:Customer....") //子类可以访问父类的protected属性和方法,但不能访问private属性和方法 override def print: Unit = println("第四行输出:Customer name:"+name+"\tCustomer age:"+age+"\tvip:"+vip+"\tphone:"+phone)}object Test extends App{ val c:User = new Customer(false,"q1234677","email@test.com") c.name= "caspar" c.age=19 //c.phone =10 这里不能访问到protected phone c.print}
Trait
Scala和Java语言一样,采用了很强的限制策略,避免了多种继承的问题。在java语言中,只允许继承一个超类,该类可以实现多个接口,但java接口有其自身的局限性:接口中只能包括抽象方法,不能包含字段、具体方法。
Scala语言利用Trait解决了该问题,在scala的trait中,它不但可以包括抽象方法还可以包含字段和具体方法。
使用with实现Trait接口
Trait中可以带有具体字段和具体方法的实现
trait有自己的构造器,它是无参构造器,不能定义trait带参数的构造器
trait的构造顺序
1. 如果有超类,则先调用超类的构造器
2. 如果有父trait,它会按照继承层次先调用父trait的构造器
2. 如果有多个父trait,则按顺序从左到右执行
3. 所有父类构造器和父trait被构造完之后,才会构造本类
trait User { //定义一个抽象方法,注意不需要加abstract def login(id:String):String def add(o:Any):Boolean def update(o:Any):Int def query(id:String):List[Any]}trait Vip { def info(vip:Boolean):Boolean //带有具体字段 private var num = 0 //带有具体方法和属性的实现 def upgrade={ num+=1 println("升级成"+num+"号vip 会员") }}class Customer extends User with Vip{ override def login(id: String)=id override def add(o: Any): Boolean = { if(o==null) false else true } override def update(o: Any): Int = { if(o==null) 0 else 1 } override def query(id: String): List[Any] = List(id,"aaa","bbb") override def info(vip: Boolean): Boolean = vip}object Test extends App{ val u = new Customer Predef println u.login("userid 001") println(u.add("add user")) println(u.update("update user")) println((u query "userid 001").mkString(",")) println("vip:"+u.info(false)) u.upgrade u.upgrade}
自身类型(=>)
用法一
class OuterClass { outer => //定义了一个外部类别名 val v1 = "here" class InnerClass { // 用outer表示外部类,相当于OuterClass.this println(outer.v1) }}
用法一
trait User { //定义一个抽象方法,注意不需要加abstract def login(id:String):String}class Customer{ //self:User => 要求Customer在实例化时或定义Customer的子类时 //必须混入指定的User trait,这个User类型也可以指定为当前类型 self:User=>}//类Test扩展Customer的时候必须混入trait User//否则的话会报错object Test extends Customer with User{ override def login(id: String): String = id+" login..." def main(args: Array[String]): Unit = { println(login("001")) }}
包对象
包对象主要用于将常量、工具函数,使用时直接通过包名引用
包对象的定义
package com.scala.test
利用package关键字定义单例对象
package object Id{ var id=0 def autoIncrementId:Int={ id+=1 id }}object Test extends App{ println(Id.autoIncrementId) println(Id.autoIncrementId) println(Id.autoIncrementId)}
访问控制
在java语言中,主要通过public、private、protected及默认控制来实现包中类成员的访问控制,当定义一个类时,如果类成员不加任何访问控制符时,表示该类成员在定义该类的包中可见。在scala中没有public关键字,仅有private 和 protected访问控制符,当一个类成员不加private和protected时,它的访问权限就是public。下面逐个进行讲解:
private 成员
private成员同java是一样的,所有带该关键字修饰的成员仅能在定义它的类或对象中使用,在外部是不可见的
protected 成员
在java语言中,protected成员不但可以被该类及其子类访问,也可以被同一个包中的其它类使用,但在scala中,protected成员只能被该类及其子类访问
无修饰符成员
无修饰符的成员同java 的public,可以在任何位置进行访问
范围保护
在scala中提供了更为灵活的访问控制方法,private、protected除了可以直接修饰成员外,还可以以private[X]、protected[X]的方式进行更为灵活的访问控制,这种访问控制的意思是可以将private、protected限定到X,X可以是包、类,还可以是单例对象
private[this],限定只有该类的对象才能访问,称这种成员为对象私有成员
private,定义的类及伴生对象可以访问
访问规则表
import
隐式引入
可以直接使用包中或对象中所有的类和方法,称这种引入会隐式引入
scala默认导入以几个包:
import java.lang_
import scala._
import Predef._
重命名
scala中允许对引入的类或方法进行重命名,如果我们需要在程序中同时使用java.util.HashMap及scala.collection.mutable.HashMap时,可以利用重命名的方法消除命名冲突的问题
将java.util.HashMap重命名为JavaHashMap
import java.util.{ HashMap ⇒ JavaHashMap }
import scala.collection.mutable.HashMap
类隐藏
通过HashMap⇒ _,这样类便被隐藏起来了
import java.util.{HashMap⇒ _,_}
import scala.collection.mutable.HashMap
- Scala进阶
- Scala进阶
- scala进阶
- scala学习二:scala进阶
- Scala进阶编程指南
- Scala进阶实战
- scala进阶1-泛型
- Scala函数进阶
- scala基础5-函数进阶
- scala基础7-数组进阶
- Scala入门之函数进阶
- scala进阶6-多重界定
- scala进阶7-类型约束
- scala进阶10-路径依赖
- scala进阶11-结构类型
- scala进阶12-复合类型
- scala进阶13-中值表达式
- scala进阶15-依赖注入
- 对JESSIONID理解
- python新手自学-list
- np.max 与 np.maximum
- H5游戏开发之phaser学习笔记(一)
- cin输入函数
- Scala进阶
- 动态规划的描述与分析方法——《算法导论》
- 如果你不想做某些事情,那就找个对象吧, 让对象代你做!
- PL/SQL 编程初步理解
- CookieUtils
- 送给初学者的前端经验分享
- 05-S3C2440学习之内核(移植)linux3.4.2移植(1)之简单移植+修改MTD分区+制作jffs2文件系统
- DataGroup
- Spring 表达式