快学Scala-类、对象、继承、特质

1、类
1、类的定义和访问限制符

/**
  * 类的定义,变量声明与访问限制
  * 在Scala中,类并不用声明为public。
  *Scala源文件中可以包含多个类,所有这些类都具有公有可见性。
  * Created by 12706 on 2017/11/27.
  */
//private[scu]:包可见性scu是包名,除了该包和子包其他包不可见
//Person private表示构造器(无参的主构造器)私有化了,除了伴生对象外其他对象里面一旦创建运行会出错
private[scu] class Person private {

  //val修饰的属性,外部只能访问该属性而不能修改(反编译后能看到只有get方法而没有set方法)
  val id = 110
  //var 修饰的属性,既有get方法也有set方法
  var name = "小明"

  //private修饰的属性(类私有字段)只能在当前类(以及伴生对象 object Person)中访问
  private val age : Int = 18

  //对象私有字段,访问权限更加严格的,连伴生对象都不能访问,只能当前类才行
  private[this] val height : Int = 16

  //getHeight()当然也行
  private def getHeight = {
    height
  }

}

//伴生对象,类和伴生对象之间可以相互访问私有的方法和属性
object Person {

  def main(args: Array[String]): Unit = {
    //创建对象,当然用new Person()也行
    val p = new Person

    //访问对象属性,访问不到height属性
    println("id:" + p.id)
    println("姓名:" + p.name)
    println("年龄:" + p.age)
    //通过方法获height属性
    val height = p.getHeight;
    println("身高:" + height)

    //修改属性,只能修改到name
    p.name = "小雨"
    println("姓名:" + p.name)

  }

}

class Man {}
object Man {
  def main(args: Array[String]): Unit = {
//    运行会出错,因为构造器被私有化了
//   val p = new Person
  }
}

对上面的demo进行反编译,java代码一目了然

public class Person
{
  private final int id = 110;

  private String name = "小明";

  private final int main$java$cn$scu$scala$day02$Person$$age = 18;

  private final int height = 16;

  public static void main(String[] paramArrayOfString)
  {
    Person..MODULE$.main(paramArrayOfString);
  }

  public int id()
  {
    return this.id;
  }
  public String name() { return this.name; } 
  public void name_$eq(String x$1) { this.name = x$1; }

  public int main$java$cn$scu$scala$day02$Person$$age() {
    return this.main$java$cn$scu$scala$day02$Person$$age;
  }

  public int main$java$cn$scu$scala$day02$Person$$getHeight()
  {
    return this.height;
  }
}

2、构造器

/**
  * 每个类都有主构造器,主构造器的参数直接放置类名后面,与类交织在一起
  * Created by 12706 on 2017/11/27.
  */
//height : Int 相当于private[this] height : int
//反编译的时候能看到成员变量有id,name,age
class People(val id : Int, var name : String, height : Int, private var age : Int = 18)  {

}

object People {
  def main(args: Array[String]): Unit = {

    //age有初始值所以创建对象时可以不指定
    val p = new People(1,"小明",60);
    //访问不了height属性,height为对象私有字段
    println(p.id + " " +p.age + " " +p.name)

    val p2 = new People(1,"小明",60,28);
    println(p2.id + " " +p2.age + " " +p2.name)

  }
}
输出
1 18 小明
1 28 小明
/**
  * 辅助构造器的定义
  * Created by 12706 on 2017/11/27.
  */
class Student(val id : Int, val name : String) {

  println("执行主构造器!")

  //用this关键字定义辅助构造器
  def this(id : Int, name : String, age : Int){
    //每个辅助构造器必须以主构造器或其他的辅助构造器的调用开始
    this(id,name)
    println("执行辅助构造器")
  }
}
object Student {
  def main(args: Array[String]): Unit = {
    val stu = new Student(1,"小明",20)
    //同样还是访问不到age的
    println(stu.name)
  }
}
/**
  * 主构造器会执行类定义中的所有语句
  * Created by 12706 on 2017/11/27.
  */
class Prop {

  println("执行主构造器")

  //定义方法
  def method(): Unit ={
    println("用我来读取文件内容 !")
  }

  //读取外部文件内容
  try {
    //读取的整个文件后转为String
    val context = Source.fromFile("d://words.txt").mkString
    println(context)
  }catch {
    case e :Exception => e.printStackTrace()
  }finally {
    println("读取文件完毕")
  }


}
object Prop {
  def main(args: Array[String]): Unit = {
      val prop = new Prop
      println("================")

      prop.method
  }
}
输出
执行主构造器
hello tom
hello jerry
hello tom
hello jerry
hello tom
hello tom
读取文件完毕
================
用我来读取文件内容 !

2、对象
1、单例对象
在Scala中没有静态方法和静态字段,但是可以使用object这个语法结构来达到同样的目的
1.存放工具方法和常量
2.高效共享单个不可变的实例
3.单例模式

/**
  * java中SessionFactory(hibernate或者是mybatis(SqlSessionFactory))的设计就是
  * 单例的,通过它来获取Session对象。使用scala来进行简单模拟
  * Created by 12706 on 2017/11/27.
  */
//下面相当于java的静态块
object SessionFactory{
  var counts = 5;
  val buffer = new ArrayBuffer[Session](5)
  while (counts>0) {
    //给buffer缓存塞入5个Sessio对象
    val session = new Session
    buffer += session
    counts -= 1
  }

  //获取session对象,相当于java的静态方法
  def getSession(): Unit ={
    //缓存中取session
    buffer.remove(0)
  }

  def main(args: Array[String]): Unit = {
    //单例对象,不需要new,用【类名.方法】调用对象中的方法
    val session = SessionFactory.getSession
    println(session)
  }
}
class Session {
}

2、伴生对象
在Scala的类中,与类名相同的对象叫做伴生对象,类和伴生对象之间可以相互访问私有的方法和属性

/**
  * 伴生对象与类之间私有属性的访问
  * Created by 12706 on 2017/11/27.
  */
class Dog {
  private val name : String = "旺财"
  def bark(){
    //访问伴生对象的私有属性
    println(Dog.voice)
  }
}
object Dog {
 private val voice : String = "wangwang"

  def main(args: Array[String]): Unit = {
    val dog = new Dog
    //访问对象的私有name属性
    println(dog.name)
    dog.bark()
  }
}

2、apply方法

/**
  * apply方法:通常我们会在类的伴生对象中定义apply方法,
  * 当遇到类名(参数1,...参数n)时apply方法会被调用
  * Created by 12706 on 2017/11/27.
  */
class Point {

  private var x : Int = 2

  println("主构造器被调用")

  def this(x : Int){
    this()
    this.x = x
  }

}

object Point {

  def apply(): Unit ={
    println("apply()方法被调用")
  }

  def apply(x : Int, y : Int): Unit = {
    println("apply(x : Int, y : Int)方法被调用")
  }

  def apply(x : Int): Point = {
    println("apply(x : Int)方法被调用")
    new Point(x)
  }

  def main(args: Array[String]): Unit = {

    val p1 = new Point
    println("===================")
    //注意两者区别,调用apply方法的时候不会执行主构造器方法
    val p2 = Point()

    val p3 = Point(3,4)
    println("===================")

    val p4 = Point(3)
    println(p4.x)
  }
}
输出
主构造器被调用
===================
apply()方法被调用
apply(x : Int, y : Int)方法被调用
===================
apply(x : Int)方法被调用
主构造器被调用
3

4、应用程序对象
Scala程序都必须从一个对象的main方法开始,可以通过扩展App特质,不写main方法。

/**
  * 应用程序对象,单例对象(或者伴生对象)继承App即可,App中定义了main方法被继承过来了
  * 所以AppDemo中不需要写main方法了
  * Created by 12706 on 2017/11/27.
  */
object AppDemo extends App{
  val arr = Array(1,2,3,4)
  println(arr.toBuffer)
}

3、继承
1、拓展类
在Scala中扩展类的方式和Java一样都是使用extends关键字,但是并没有使用implements来实现接口,都是用extends。如果继承一个类的同时也实现了很多接口,那么用extends 父类 with 接口1 with 接口2 with…

2、方法的重写
方法重写就是子类中对父类的方法实现重写。
java中接口中都是抽象方法,但是scala中可以有实现,而且关键字是trait称为特质。但是重写一个非抽象方法必须使用override关键字。

3、类型检查和转换
obj.isInstanceOf[C](scala中) ,obj instanceof C(java中)。obj是不是C类型
obj.asInstanceOf[C](scala中),(C)obj(java中),obj类型强转为C类型。
classOf[C](scala中),C.class。获取C类型

/**
  * Men是Human类(继承类),同时拥有动物的行为(实现接口)
  * Created by 12706 on 2017/11/27.
  */
//Human是类必须接在extends后面
class Men extends Human with Animall{
  def say(): Unit = {
    println("大家好,我的名字叫:" + name)
  }

  //重写父类已经实现的方法需要加override关键字,父类没实现那么可加可不加
  override def getName(): String = {
    this.name
  }
}
object Men {
  def main(args: Array[String]): Unit = {
    val man = new Men
    man.name = "xiaoming"

    man.say()
    println(man.getName())

    //类型检查
    val b = man.isInstanceOf[Animall]
    println(b)

  }
}

abstract class Human {
  var name : String = _
  def say()
}

trait Animall {

  def getName(): String = {
    "monkey"
  }
}
输出
大家好,我的名字叫:xiaoming
xiaoming
true

猜你喜欢

转载自blog.csdn.net/qq_37334135/article/details/78649033
今日推荐