Scala面向对象
补充:Scala中class和object区别
(一)class
calss scala编译器会字段帮我们生产一个私有字段和2个公有方法get和set
scala 中没有 static 关键字,所以 对于一个class来说,所有的方法和成员变量在实例被 new 出来之前都是无法访问的
因此在class中的main方法没什么用了
(二)object
scala 的object 中所有成员变量和方法默认都是 static 的
所以可以直接访问main方法
一:类的定义
注意:默认变量时public,但是只能写private和protected两种修饰符
注意:默认在类中声明变量是,静态变量,需要我们进行初始化操作
package ClassBase class UserInfo{ //对应var变量,可以设置setter和getter private var Name:String="aaa" private var Age:Int=20; //对应val常量,只可以设置getter private val Addr:String="china" def setName(name:String)= this.Name=name def getName()= this.Name def setAge(age:Int)= this.Age=age def getAge()= this.Age def getAddr()= this.Addr } object User { def main(args:Array[String]):Unit={ var user=new UserInfo println(user.getName()+"\t"+user.getAge()+"\t"+user.getAddr()) user.setAge(10) user.setName("aggw") println(user.getName()+"\t"+user.getAge()+"\t"+user.getAddr()) } }
注意:允许类中包含内部类
二:类的构造器
分为两种:主构造器和辅助构造器
(一)主构造器
主构造器和类的声明放在一起,只能有一个主构造器。
//主构造器 class Stu(var StuName:String,var StuAge:Int){ } object User { def main(args:Array[String]):Unit={ var s = new Stu("aaa",12) println(s.StuName+"\t"+s.StuAge); } }
(二)辅助构造器
辅助构造器可以有多个,使用关键字this实现。
package ClassBase class UserInfo{ //对应var变量,可以设置setter和getter private var Name:String="aaa" private var Age:Int=20 //对应val常量,只可以设置getter private val Addr:String="china" def setName(name:String)= this.Name=name def getName()= this.Name def setAge(age:Int)= this.Age=age def getAge()= this.Age def getAddr()= this.Addr } //主构造器 class Stu(var StuName:String,var StuAge:Int){ private var StuAddr:String="" //辅助构造器 def this(name:String){ this(name,20) } } object User { def main(args:Array[String]):Unit={ //主构造器 var s = new Stu("aaa",12) println(s.StuName+"\t"+s.StuAge); //辅助构造器 var s_2 = new Stu("ge") println(s_2.StuName+"\t"+s_2.StuAge); } }
三:单例对象
在Scala中,单例对象分为两种,一种是并未自动关联到特定类上的单例对象,称为独立对象(Standalone Object);
另一种是关联到一个类上的单例对象,该单例对象与该类共有相同名字,则这种单例对象称为伴生对象(Companion Object),对应类称为伴生类。
(一)单例对象(独立对象 )
Scala单例对象是十分重要的,没有像在Java一样,有静态类、静态成员、静态方法,但是Scala提供了object对象,这个object对象类似于Java的静态类,它的成员、它的方法都默认是静态的。
注意:如果object的静态成员要被外界访问,则该成员不能被private修饰
object People{ var users = new ArrayBuffer[String]() def addUser(user:String){ println(s"add user ${user}") users += user } def getUsers(){ for(u<-users)println(u) } } object ObjTest{ def main(args:Array[String]):Unit={ var user1 = People var user2 = People user1.addUser("aaa") user2.addUser("bbb") println("--------------") user1.getUsers() println("--------------") user2.getUsers() } }
(二)单例对象(伴生对象 )
如果有同样一个类与该object名字一样,则称该object为该类的伴生对象,相对应,该类为object的伴生类。如果一个类有它的伴生对象,这个类就可通过object的名字访问到所有成员。
class People{ var users = new ArrayBuffer[String]() //People.newId+=1 var newId = { People.id } def addUser(user:String){ newId+=1 println(s"add user ${user} ${newId}") users += s"${user} ${newId}" } def getUsers(){ for(u<-users)println(u) } } object People{ private var id = 0 private var obj:People = _ //下划线为默认值,为空 def apply()={ if(obj==null){ obj=new People obj }else{ obj } } } object ClassTest{ def main(args:Array[String]):Unit={ var p = People() var p2=People() p.addUser("aaa") p2.addUser("ffff") p.getUsers() p2.getUsers() } }
注意:apply方法
apply是Scala的一种语法,在遇到形如object(arg1,arg2....argN)这样的表达式时,apply方法就会被调用
apply方法需要定义在伴生对象中
注意:当object和class同时出现时,会去访问object,而不是去访问class。所以实现的单例模式无歧义
伴生对象与伴生类在Scala的面向对象编程方法中占据极其重要的位置,例如Scala中许多工具方法都是由伴生对象提供的。
总之:就是将静态成员和静态方法,全部独立到object,没有其他较大差别
补充:Scala 中 _ 代表什么
Scala中“_”代表什么
四:类继承extends
Scala跟Java一样,是单继承,所以子类只能有一个父类
下面的例子中,子类Employee重写了Person类的字段,所以在重写的部分前使用了override关键字,extends后面也加上了重写的字段。同时还重写了父类的sayHello方法,所以在重写的方法前也使用了override关键字.
而对象p3则是在main方法中通过父类实例化的,这种叫做匿名子类,而且通过重写父类的方法我们可以看到效果
class Parent(val name:String,val age:Int){ def say()={ s"父类调用函数" } } class Child(override val name:String,override val age:Int,val addr:String)extends Parent(name,age){ override def say()={ s"子类调用函数" } } object ClassTest{ def main(args:Array[String]):Unit={ var p1:Parent = new Parent("aaa",22) println(p1.say()) var p2:Parent = new Child("bbb",3,"g") println(p2.say()) var p3:Parent = new Parent("ccc",43){ override def say()={ s"匿名子类调用函数" } } println(p3.say()) } }
五:抽象类abstract
抽象类包含抽象字段(没有初始值的字段)抽象方法(即没有方法体的方法),且抽象类只能用于继承。子类在继承抽象类的时候,必须实现所继承的类的抽象方法。抽象类可以用来实现简单工厂模式。
abstract class Animal{ var Name:String //成员变量不能初始化 def getInfo():String //方法不能实现 } class Dog extends Animal{ var Name:String="dog" //必须设置一个值 def getInfo():String={ s"this is a ${Name}" } } object ClassTest{ def main(args:Array[String]):Unit={ var anm:Animal = new Dog println(anm.getInfo()) } }
六:特质(接口)Trait
Scala Trait本质上就是抽象类,但Trait支持多继承,相当于Java的接口,但比接口更强大,因为它可以定义抽象方法或方法。
如果要继承多个特质,只要加上with 特质名就可以了。
abstract class Animal{ var Name:String //成员变量不能初始化 def getInfo():String //方法不能实现 } trait A{ def getInfo1():String } trait B{ def getInfo2():String={ s"trait B getInfo" } } class Dog extends Animal with A with B{ var Name:String="dog" //必须设置一个值 def getInfo():String={ s"this is a ${Name}" } def getInfo1():String={ s"trait A getInfo" } } object ClassTest{ def main(args:Array[String]):Unit={ var anm:Dog = new Dog println(anm.getInfo()) println(anm.getInfo1()) println(anm.getInfo2()) } }
七:包的使用
Scala的包和Java中的包或者C++中的命名空间的目的是相同的:管理大型程序中的名称
Scala中的包可以像Java一样使用,包里包含所建立的类,而且Package是可以嵌套的
Scala中依然使用import作为引用包的关键字,如import com.my.io._可以引用com.my.io下的所有类型,import com.my.io.xxx._可以引用com.my.io.xxx的所有成员
而且Scala中的import可以写在任意地方,而Java中的import写在最前面
包可以包含类、对象、特质,但不能包含函数或者变量的定义,这是JVM的限制,而Scala中的包对象可以包含常量、变量、方法、类、对象、特质、包