Scala学习笔记-类

Scala-类

Scala学习笔记-类_第1张图片

Scala的强大之一在于它支持函数式编程,之二在于它可以Java无缝整合。所以Scala也是一门OO语言,类作为面向对象的基础概念,在Scala中也是必不可少的。

Scala类的定义与Java虽出同门,但有所区别,下面就探索一下Scala的类。

最简单的类定义

类作为对象的蓝图,在使用前要进行定义

class Test {}

这是一个没有方法,没有属性,没有构造参数的简单类,有了它,就可以创建对象

val test = new Test

有属性的类

对象通常由两部分组成:属性和方法,属性代表状态,方法代表行为。方法的定义及使用在前面以及介绍,下面具体讨论scala类中的属性。


如果熟悉Java 就会知道,JavaBean规范规定:私有属性 + getter/setter方法构成一个标准的JavaBean。在Java中构造JavaBean对象是一件很麻烦的事情

public class JvaBean1 {

    private String name;
    private String age;

    public void setName(String name) {
        this.name = name;
    }
    public String getName() { 
        return name; 
    }

    public void setAge(String age) {
        this.age = age;
    }
    public String getAge{
        return age;
    }
}

然后,Scala为了保持简洁 提高开发效率,确是为程序员做了很多工作,先看一个例子

class Test {
     var name = ""
     var age = ""
}

*由于val变量不可改变,此处用var定义来说明问题

对于Test的两个属性,用如下方式操作

object Test {
    def main(args: Array[String]) {
         val test = new Test
         test.name = "zhangsan"
         test.age = "lisi"

         println(test.name)
         println(test.age)
    }
}

属性

来看一些Test类对应的Java源码,会发现很多有意思的事

public class Test
{
  private String name = "";
  private String age = "";

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

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

正如所看到的,nameage被翻译成了标准的Javabean形式-私有属性+setter/getter,那么,很多人会有疑问了, 为什么 getter和setter方法的调用方式相同呢?


实际上, test.name = "张三"中的 name =对应于 name_$eq"zhangsan"是传入的值, 而println(test.name)中的test.name对应name() 方法,

  • 对于val变量,scala会翻译成私有字段 + getter/setter


    那么,对于val变量呢,下面来看一下

class Test{

     val name = ""

}
public class Test
{
  private final String name = "";

  public String name() { 
      return this.name;
  }
}

看到了吧,private final + getter

  • val变量会被解释成private final + getter,只能获取,不能修改

如果用private修饰变量会怎么样?

class Test{

     private var name = ""

}

java代码如下

public class Test
{
  private String name = "";

  private String name() { 
     return this.name; 
  } 
  private void name_$eq(String x$1) { 
     this.name = x$1;
  }
}
  • 被private修改的变量会被翻译成私有字段 + 私有 getter/setter

scala中还有一种更加严重的访问控制,private[this],它可以吧属性完全限制在当前对象内

class Test{
     private[this] var name = ""
}
public class Test
{
  private String name = "";
}
  • private[this]修饰的属性不会生成getter/setter方法

到此为止,已经看到了scala处理类的属性的大致思路,但同时,也会产出更大的疑惑,scala的getter/setter并不符合JavaBean规范,这样一来,scala与Java无缝兼容不久是做梦吗?因为很多工具类库都依赖于标准的JavaBean。

如果连这种简单粗暴的问题都没有解决方案,那scala还是去屎吧。看下面的例子

import scala.beans.BeanProperty
class Test{

     @BeanProperty
     var name = "zhangsan"
}
public class Test
{
  private String name = "zhangsan";

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

为属性添加@BeanProperty注解后,scala除了会生成scala规范的getter/setter,同时也生成了符合JavaBean规范的getter/setter,完美解决。

总结一下:

1.val name 生成getter
2.var name 生成getter + setter
3.private var/val name 生成私有的 getter/setter
4.private [this] val/var name 不生成getter/setter
5.@BeanProperty val/var name 同时生成符合scala和Java规范的  
  getter/setter


构造器


下面来讨论一下类是另一个组成部分:构造器。
还是先从一个简单的例子开始

class Test(name: String) { println(name) def this(name: String, age: String) { this(name) println(age) } }

然后再看一下这个简单类的Java代码

public class Test
{
  public Test(String name)
  {
    Predef..MODULE$.println(name);
  }
  public Test(String name, String age) {
    this(name);
    Predef..MODULE$.println(age);
  }
}

很简单,scala构建了一个带有一个参数的构造器,并将println脚本添到了构造器中。

从上面的简单示例中可以看到,scala的构造器定义与类定义交织在一起,即在类名后直接构建构造器参数,开始可能会感觉别扭,但会越来越发现这确实是一个即简洁又高效的做法。


上面的例子中主要包含了两部分内容:主构造器辅助构造器

主构造器

主构造器是类名后面的部分,在主构造器中可以声明任意类型的参数或 var/val。

  • 在声明参数时,指定var或val的变量,会被当成类的属性处理,处理方式同上。
class Test(@BeanProperty var name: String = "zhangsan") {

}
  • 没有指定var 或 val的参数,只有在类中使用到该变量时,才会将其升级为类的属性。
class Test(name:String) { }

辅助构造器

辅助构造器类似于Java中的构造器重载,可以使类支持多种形式的构造。辅助构造器必须直接或间接的以调用主构造器开始

class Test(name: String) { println(name) def this(name: String, age: String) { this(name) println(age) } def this(name: String, age: String, location: String){ this(name, age) println(location) } }

你可能感兴趣的:(scala)