抽象

scala的抽象关键字和java一样,都是abstract,而且抽象类都不能被实例化的。
除了类可以定义为抽象的,类的属性和方法,也可以是抽象的。
从下面的例子中,可以看到其实和java的抽象类定义没有什么区别

abstract class ScalaAbstract {
  // 抽象属性,可以没有初始值,甚至不用_
  var str1: String
  var str2: String = "str2"
  val str3: String
  val str4: String = "str4"

  /**
   * 抽象方法
   */
  def printInfo1: Unit

  def printInfo2: Unit = {
    println(s"${str1},${str2},${str3},${str4}")
  }
}

继承

和java一样,继承也是用extends关键字,概念也是同java的,包括先调用父类的构造器等。区别如下:

  1. 如果覆盖父类的非抽象方法,非抽象变量,在scala中要写override,在java中只是警告。
  2. 抽象方法,var定义的抽象变量,可以不写override,也可以写。
  3. val定义的抽象变量,要写override。
class ScalaChild extends ScalaAbstract {
  /**
   * 可以不写override
   */
  var str1: String = "str1"
  /**
   * 直接修改
   */
  str2 = "str2"
  /**
   * 必须写override
   */
  override val str3: String = "str3"
  /**
   * 必须写override
   */
  override val str4: String = "str4"

  /**
   * 抽象方法,可以不写override
   */
  def printInfo1: Unit = {
    println(s"${str1},${str2},${str3},${str4}")
  }

  /**
   * 必须写override
   */
  override def printInfo2: Unit = {
    println(s"ScalaChild:${str1},${str2},${str3},${str4}")
  }
}

object ScalaChild {
  def main(args: Array[String]): Unit = {
    val child = new ScalaChild()
    child.printInfo1
    child.printInfo2
  }
}

多态

我们先看看比较熟悉的java。
定义了一个抽象类JavaAnimal,包含一个变量name和方法eat。JavaCat和JavaDog是JavaAnimal的实现类。在main方法中通过eat方法打印。

public abstract class JavaAnimal {
    public String name = "无";

    abstract void eat();
}

public class JavaCat extends JavaAnimal {
    String name = "小猫";

    void eat() {
        System.out.println("吃鱼");
    }
}

public class JavaDog extends JavaAnimal {
    String name = "小狗";

    void eat() {
        System.out.println("吃骨头");
    }
}

public class JavaAnimalMain {
    public static void eat(JavaAnimal animal) {
        System.out.println(animal.name);
        animal.eat();
    }

    public static void main(String[] args) {
        eat(new JavaCat());
        eat(new JavaDog());
    }
}

打印结果为:

无
吃鱼
无
吃骨头

可以看到name为父类的值,但是方法却是调用子类的方法。
在scala中,实现类似的功能:

abstract class ScalaAnimal {
  var name: String = "无"

  def eat(): Unit
}

object ScalaAnimal {
  def eat(animal: ScalaAnimal): Unit = {
    println("******")
    println(animal.name)
    animal.eat()
  }

  def main(args: Array[String]): Unit = {
    eat(new ScalaCat)
    eat(new ScalaDog)
  }
}

class ScalaCat extends ScalaAnimal {
  name = "小猫"

  override def eat(): Unit = {
    println("吃鱼")
  }
}

class ScalaDog extends ScalaAnimal {
  name = "小狗"

  override def eat(): Unit = {
    println("吃骨头")
  }
}

打印结果:

******
小猫
吃鱼
******
小狗
吃骨头

name打印的是子类的name。
所以java中属性是静态绑定,方法是动态绑定。而scala中,属性和方法都是动态绑定。


大军
847 声望183 粉丝

学而不思则罔,思而不学则殆


引用和评论

1 篇内容引用
0 条评论