Scala的面向对象编程风格带有一些语法糖和一些技巧。
为了更好地了解Scala的工作原理,我们将研究一些Scala示例和相应的字节代码(实际上是反编译类文件所产生的Java代码)。
Examples Empty Class 最简单的例子,一个空的类。这里只有一个带有无参数构造函数的类,这不足为奇。顺便说一句,如本例所示,Scala中的默认可见性修饰符是public
//Scala
class Empty
//Java
public class Empty {}
有参数但没有字段的类 带有参数的构造函数的类:它导致带有all-args构造函数的类。 任何方法之外的类的主体都被视为构造函数定义的一部分。
//Scala
class Fraction(n: Int, d: Int) {
System.out.println("numerator:" + n + ", denominator:" + d)
}
//Java
public Fraction(final int n, final int d) {
System.out.println("numerator:" + n + ", denominator:" + d);
}
具有参数提升为字段的类 当构造函数的参数由构造函数以外的类的成员使用时,这些参数将提升为字段,以便可以对其进行访问。
//Scala
class FractionString(n: Int, d: Int){
override def toString: String = n + "/" + d
}
//Java
public class FractionString {
private final int n;
private final int d;
public String toString() {
return this.n + "/" + this.d;
}
public FractionString(final int n, final int d) {
this.n = n;
this.d = d;
}
}
值得注意的是,生成的字段的可见性是对象专用的(private [this]),这意味着它们不能被同一类的其他对象访问。例如,此示例将无法编译:
//Scala
class FractionEqual(n: Int, d: Int){
override def equals(other: Any): Boolean = other match {
case that: FractionEqual => n == that.n && d == that.d
case _ => false
}
}
Error:(32, 43) value n is not a member of FractionEqual
case that: FractionEqual => n == that.n && d == that.d
有趣的是,修饰符private [this]在JVM中没有意义,因此被编译为private。
带参数字段的类 关键字val可以用作同时定义参数和名称相同的字段的简写形式。该字段伴随有一个名为字段的吸气剂。
//Scala
class FractionVal(val n: Int, val d: Int)
//Java
public class FractionVal {
private final int n;
private final int d;
public int n() {
return this.n;
}
public int d() {
return this.d;
}
public FractionVal(final int n, final int d) {
this.n = n;
this.d = d;
}
}
但是,所有设计都是为了制造一种幻想,即没有方法。在这种情况下,将getter定义为无参数方法,因此客户端将忽略他们正在调用val还是def。 这是Scala支持统一访问原则的方式:
客户端代码不应受到将属性实现为字段或方法的决定的影响。
不幸的是,这在Java版本中无法理解,因为它显示了用括号定义的方法,一个空括号的方法,因为在JVM领域中不存在无参数方法。
但是,以下示例说明了它在Scala中的工作方式:
scala> class FractionVal(val n: Int, val d: Int)
defined class FractionVal
scala> val f = new FractionVal(1,2
f: FractionVal = FractionVal@2102eb7a
scala> f.n
res17: Int = 1
scala> f.d
res18: Int = 2
scala> f.n()
<console>:13: error: Int does not take parameters
f.n()
现在,将有可能实现的方法等于S作为字段都可以通过相应的公共访问干将。
带有var的参数字段 也可以使用关键字var定义参数字段。在这种情况下,还将生成一个名为field_ =的设置器。
//Scala
class FractionVar(var n: Int, var d: Int)
//Java
public class FractionVar {
private int n;
private int d;
public int n() {
return this.n;
}
public void n_$eq(final int x$1) {
this.n = x$1;
}
public int d() {
return this.d;
}
public void d_$eq(final int x$1) {
this.d = x$1;
}
public FractionVar(final int n, final int d) {
this.n = n;
this.d = d;
super();
}
}
与前面的示例类似,将setter field_ =解释为赋值运算符,以产生没有方法的错觉。尽管在这种情况下,也可以直接调用设置器:
scala> class FractionVar(var n: Int, var d: Int)
defined class FractionVar
scala> val f = new FractionVar(1,2)
f: FractionVar = FractionVar@1ecdfe1e
scala> f.n
res20: Int = 1
scala> f.n = 9
f.n: Int = 9
scala> f.n
res21: Int = 9
scala> f.n_=(10)
scala> f.n
res24: Int = 10
生成的getter / setter 的可见性与相应的val / var的可见性相同
带有自定义Getter / Setter的类 按照Java的传统,我们还可以创建自己的getter / setter方法。但是,对变量的访问仍然是通过合成的getter / setter完成的。
//Scala
class FractionVar(var n: Int, var d: Int){
def setN(n: Int) = this.n = n
def getN() = n
}
//Java
public class FractionVar {
private int n;
private int d;
public int n() {
return this.n;
}
public void n_$eq(final int x$1) {
this.n = x$1;
}
public int d() {
return this.d;
}
public void d_$eq(final int x$1) {
this.d = x$1;
}
public void setN(final int n) {
this.n_$eq(n);
}
public int getN() {
return this.n();
}
public FractionVar(final int n, final int d) {
this.n = n;
this.d = d;
super();
}
}
这是有关如何使用新方法的示例。注意如何在带或不带括号的情况下调用getN
scala> :paste
// Entering paste mode (ctrl-D to finish)
class FractionVar(var n: Int, var d: Int){
def setN(n: Int) = this.n = n
def getN() = n
}
// Exiting paste mode, now interpreting.
defined class FractionVar
scala> val f = new FractionVar(1,2)
f: FractionVar = FractionVar@125490ea
scala> f.getN()
res26: Int = 1
scala> f.getN
res27: Int = 1
scala> f.setN(9)
scala> f.getN
res29: Int = 9
Object 对象被编译为两个类:
名称后缀为$并包含实际功能的单例 具有静态转发器的类,以访问单例功能。
//Scala
object FractionObject {
def fraction(n: Int, d: Int) = n + "/" + d
}
//Java
public final class FractionObject$ {
public static FractionObject$ MODULE$;
static {
new FractionObject$();
}
public String fraction(final int n, final int d) {
return n + "/" + d;
}
private FractionObject$() {
MODULE$ = this;
}
}
public final class FractionObject {
public static String fraction(int var0, int var1) {
return FractionObject$.MODULE$.fraction(var0, var1);
}
}
Companion Object Scala中的伴随对象是与类在同一文件中声明的对象,并且与该类具有相同的名称。与前面的情况类似,创建了一个单例和一个转发器。 唯一的区别是,现在单例实现了AbstractFunction(具有相应的-arity)和Serializable。
//Scala
class FractionVal(val n: Int, val d: Int)
object FractionVal
//Java
public final class FractionVal$ extends AbstractFunction2 implements Serializable {
public static FractionVal$ MODULE$;
static {
new FractionVal$();
}
public final String toString() {
return "FractionVal";
}
public FractionVal apply(final int n, final int d) {
return new FractionVal(n, d);
}
public Option unapply(final FractionVal x$0) {
return (Option)(x$0 == null ? .MODULE$ : new Some(new sp(x$0.n(), x$0.d())));
}
private Object readResolve() {
return MODULE$;
}
// $FF: synthetic method
// $FF: bridge method
public Object apply(final Object v1, final Object v2) {
return this.apply(BoxesRunTime.unboxToInt(v1), BoxesRunTime.unboxToInt(v2));
}
private FractionVal$() {
MODULE$ = this;
}
}
public class FractionVal {
private final int n;
private final int d;
public int n() {
return this.n;
}
public int d() {
return this.d;
}
public FractionVal(final int n, final int d) {
this.n = n;
this.d = d;
}
}
有趣的是,由于FractionVal没有任何对FractionVal $的引用,因此在Scala中无法使用单例实现的功能。 例如,方法apply不可用,而toString使用Object.toString给定的实现,而不是FractionVal $ .toString
scala> :paste
// Entering paste mode (ctrl-D to finish)
class FractionVal(val n: Int, val d: Int)
object FractionVal
// Exiting paste mode, now interpreting.
defined class FractionVal
defined object FractionVal
scala> FractionVal(1,2)
<console>:13: error: FractionVal.type does not take parameters
FractionVal(1,2)
^
scala> new FractionVal(1,2)
res5: FractionVal = FractionVal@7f2c995b
Case Class 案例类是具有大量功能的常规类。
这是结果类的结构:
//Scala
case class FractionVal(n: Int, d: Int)
//Java
import scala.Option;
import scala.Serializable;
import scala.Some;
import scala.None.;
import scala.Tuple2.mcII.sp;
import scala.runtime.AbstractFunction2;
import scala.runtime.BoxesRunTime;
public final class FractionVal$ extends AbstractFunction2 implements Serializable {
public static FractionVal$ MODULE$;
static {
new FractionVal$();
}
public final String toString() {
return "FractionVal";
}
public FractionVal apply(final int n, final int d) {
return new FractionVal(n, d);
}
public Option unapply(final FractionVal x$0) {
return (Option)(x$0 == null ? .MODULE$ : new Some(new sp(x$0.n(), x$0.d())));
}
private Object readResolve() {
return MODULE$;
}
// $FF: synthetic method
// $FF: bridge method
public Object apply(final Object v1, final Object v2) {
return this.apply(BoxesRunTime.unboxToInt(v1), BoxesRunTime.unboxToInt(v2));
}
private FractionVal$() {
MODULE$ = this;
}
}
import scala.Function1;
import scala.Option;
import scala.Product;
import scala.Serializable;
import scala.collection.Iterator;
import scala.reflect.ScalaSignature;
import scala.runtime.BoxesRunTime;
import scala.runtime.Statics;
import scala.runtime.ScalaRunTime.;
public class FractionVal implements Product, Serializable {
private final int n;
private final int d;
public static Option unapply(final FractionVal x$0) {
return FractionVal$.MODULE$.unapply(var0);
}
public static FractionVal apply(final int n, final int d) {
return FractionVal$.MODULE$.apply(var0, var1);
}
public static Function1 tupled() {
return FractionVal$.MODULE$.tupled();
}
public static Function1 curried() {
return FractionVal$.MODULE$.curried();
}
public int n() {
return this.n;
}
public int d() {
return this.d;
}
public FractionVal copy(final int n, final int d) {
return new FractionVal(n, d);
}
public int copy$default$1() {
return this.n();
}
public int copy$default$2() {
return this.d();
}
public String productPrefix() {
return "FractionVal";
}
public int productArity() {
return 2;
}
public Object productElement(final int x$1) {
Integer var10000;
switch(x$1) {
case 0:
var10000 = BoxesRunTime.boxToInteger(this.n());
break;
case 1:
var10000 = BoxesRunTime.boxToInteger(this.d());
break;
default:
throw new IndexOutOfBoundsException(BoxesRunTime.boxToInteger(x$1).toString());
}
return var10000;
}
public Iterator productIterator() {
return .MODULE$.typedProductIterator(this);
}
public boolean canEqual(final Object x$1) {
return x$1 instanceof FractionVal;
}
public int hashCode() {
int var1 = -889275714;
var1 = Statics.mix(var1, this.n());
var1 = Statics.mix(var1, this.d());
return Statics.finalizeHash(var1, 2);
}
public String toString() {
return .MODULE$._toString(this);
}
public boolean equals(final Object x$1) {
boolean var10000;
if (this != x$1) {
label51: {
boolean var2;
if (x$1 instanceof FractionVal) {
var2 = true;
} else {
var2 = false;
}
if (var2) {
FractionVal var4 = (FractionVal)x$1;
if (this.n() == var4.n() && this.d() == var4.d() && var4.canEqual(this)) {
break label51;
}
}
var10000 = false;
return var10000;
}
}
var10000 = true;
return var10000;
}
public FractionVal(final int n, final int d) {
this.n = n;
this.d = d;
Product.$init$(this);
}
}
Case Object 也可以定义案例对象。再次,创建一个单例和一个转发器。最值得注意的是,单例实现Serializable和Product。
//Scala
`
case object FractionObject
//Java
import scala.collection.Iterator;
public final class FractionObject {
public static String toString() {
return FractionObject$.MODULE$.toString();
}
public static int hashCode() {
return FractionObject$.MODULE$.hashCode();
}
public static boolean canEqual(final Object x$1) {
return FractionObject$.MODULE$.canEqual(var0);
}
public static Iterator productIterator() {
return FractionObject$.MODULE$.productIterator();
}
public static Object productElement(final int x$1) {
return FractionObject$.MODULE$.productElement(var0);
}
public static int productArity() {
return FractionObject$.MODULE$.productArity();
}
public static String productPrefix() {
return FractionObject$.MODULE$.productPrefix();
}
}
import scala.Product;
import scala.Serializable;
import scala.collection.Iterator;
import scala.runtime.BoxesRunTime;
import scala.runtime.ScalaRunTime.;
public final class FractionObject$ implements Product, Serializable {
public static FractionObject$ MODULE$;
static {
new FractionObject$();
}
public String productPrefix() {
return "FractionObject";
}
public int productArity() {
return 0;
}
public Object productElement(final int x$1) {
throw new IndexOutOfBoundsException(BoxesRunTime.boxToInteger(x$1).toString());
}
public Iterator productIterator() {
return .MODULE$.typedProductIterator(this);
}
public boolean canEqual(final Object x$1) {
return x$1 instanceof FractionObject$;
}
public int hashCode() {
return 1259148289;
}
public String toString() {
return "FractionObject";
}
private Object readResolve() {
return MODULE$;
}
private FractionObject$() {
MODULE$ = this;
Product.$init$(this);
}
}
Trait Trait被编译为接口
//Scala
trait FractionTrait{
val n: Int
val d: Int
}
//Java
public interface FractionTrait {
int n();
int d();
}
Abstract Class 具体类的规则也适用于抽象类
//Scala
abstract class AbstractFraction(val n: Int, val d: Int)
//Java
public abstract class AbstractFraction {
private final int n;
private final int d;
public int n() {
return this.n;
}
public int d() {
return this.d;
}
public AbstractFraction(final int n, final int d) {
this.n = n;
this.d = d;
}
}
Package Object 包对象被视为对象。创建两类:一单叫包$和代理类称为包
//Scala
package object mypackage {
def greet() = "hello"
}
//Java
package mypackage;
public final class package {
public static String greet() {
return package$.MODULE$.greet();
}
}
public final class package$ {
public static package$ MODULE$;
static {
new package$();
}
public String greet() {
return "hello";
}
private package$() {
MODULE$ = this;
}
}
原文链接:http://codingdict.com