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中的包对象可以包含常量、变量、方法、类、对象、特质、包

 

posted @ 2020-03-10 10:01  山上有风景  阅读(297)  评论(0编辑  收藏  举报