Abstract vals && Abstract vars
在scala中抽象类和特质都可以定义抽象的成员变量。
abstract class Abstract { type T def transform(x: T): T val initial: T var current: T } class Concrete extends Abstract { override type T = String override def transform(x: T): T = x + x //在Java里这是final变量,所以必须要初始化赋值 override val initial: T = "string" //在Java里这个private类型变量,在scala中可以yoga下划线赋值 override var current: T = _ } object Main9 { def main(args: Array[String]): Unit = { val c = new Concrete println(c.initial) //string println(c.current) //null } }
如上的示例,定义两个抽象的成员变量,
val initial: T var current: T
同时实现类实现抽象类的时候必须要赋值重写。在Java里看起来很怪,那么在Java里是如何实现的呢,通过javap反编译看一下
C:\WorkSpace5-gitosc\scala-sample\out\production\scala-sample\com\usoft3>javap -p Abstract.class Compiled from "test.scala" public abstract class com.usoft3.Abstract { public abstract java.lang.Object transform(java.lang.Object); public abstract java.lang.Object initial(); public abstract java.lang.Object current(); public abstract void current_$eq(java.lang.Object); public com.usoft3.Abstract(); } C:\WorkSpace5-gitosc\scala-sample\out\production\scala-sample\com\usoft3>javap -p Concrete.class Compiled from "test.scala" public class com.usoft3.Concrete extends com.usoft3.Abstract { private final java.lang.String initial; private java.lang.String current; public java.lang.String transform(java.lang.String); public java.lang.String initial(); public java.lang.String current(); public void current_$eq(java.lang.String); public void current_$eq(java.lang.Object); public java.lang.Object current(); public java.lang.Object initial(); public java.lang.Object transform(java.lang.Object); public com.usoft3.Concrete(); }
其实在scala中定义的抽象字段在反编译后的java类中,其实就是抽象方法,
public abstract java.lang.Object initial(); public abstract java.lang.Object current();
那么也就不难理解了。
如下定义的抽象类中含有两个抽象变量
abstract class Abstract { val numerArg: Int val denomArg: Int }
javap 反编译Abstract抽象类
C:\WorkSpace5-gitosc\scala-sample\out\production\scala-sample\com\usoft4>javap -p Abstract.class Compiled from "test.scala" public abstract class com.usoft4.Abstract { public abstract int numerArg(); public abstract int denomArg(); public com.usoft4.Abstract(); }
scala中实现抽象类的方式最简单的如下,同时也必须重写抽象变量
new Abstract { override val denomArg: Int = 1 override val numerArg: Int = 2 }
我们打印一下这个实现类的className
println(new Abstract { override val denomArg: Int = 1 override val numerArg: Int = 2 }.getClass.getName)
com.usoft4.Main9$$anon$1,javap反编译
C:\WorkSpace5-gitosc\scala-sample\out\production\scala-sample\com\usoft4>javap -p Main9$$anon$1.class Compiled from "test.scala" public final class com.usoft4.Main9$$anon$1 extends com.usoft4.Abstract { private final int denomArg; private final int numerArg; public int denomArg(); public int numerArg(); public com.usoft4.Main9$$anon$1(); }
反编译的Abstract抽象类中是没有定义的成员变量的,只是在抽象类的实现类中出现了父类的成员变量。
这其实就是Java中的匿名类的概念。
=================END=================