本文共 6822 字,大约阅读时间需要 22 分钟。
[TOC]
需要说明的是,官方给出的参考资料对于这方面讲解得十分详细,目前入门来说,不需要达到这样的理解,只需要可以进行开发即可,这一部分我给出的是官方的一些文档说明,但是后面的定制和注解,就直接简单说明能用就好了。
class PersonOps { private var age = 0 //你必须初始化一个字段 def increment() {age += 1} //方法默认是公有的 def currentAge() = age}
1)在Scala中,类并不声明为public。Scala源文件可以包含多个类,所有这些类都具有公有可见性。
2)如何进行调用?
object MainOps{ def main(args: Array[String]) { val personOps = new PersonOps personOps.increment() println("currentAge=> " + personOps.currentAge()) }}
3)不能用类直接调用age,因为age是私有字段,只能在PersonOps中访问到。
4)无参方法
println("currentAge=>" + personOps.currentAge())println("currentAge=>" + personOps.currentAge)
建议:对设置值的时候,即改变对象状态值或者状态时使用(),而对于取值来说(不会改变对象的状态和值)去掉()是个不错的风格,这也是我们事例中的方法。
personOps.increment()println("currentAge=> " + personOps.currentAge)
5)你可以通过以不带()的方式声明currentAge来强制这种风格:
class PersonOps { private var age = 0 //你必须初始化一个字段 def increment() {age += 1} //方法默认是公有的 def currentAge = age}
结果:这样一来在调用时,必须要用不带()的进行方法调用
println("currentAge=>" + personOps.currentAge)
6)带getter和setter的属性
Java中属性定义
public class PersonAge{ //这是Java private int age; public int getAge() { return age; } public void setAge(int age) { this.age=age; }}
getter和setter方式比共有字段(public)好在什么地方呢?
之所以说getter和setter方法比公有字段更好,是因为它们让你可以从简单的get/set机制出发,并在需要的时候做改进。
5)scala中的getter和setter方法
class PersonA{ var age = 0}
a.Scala生成面向JVM的类,其中有一个私有的age字段以及相应的getter方法和setter方法。这两个方法是公有的,因为我们没有将age声明为private。而对私有字段而言,getter和setter方法也是私有的。
a.在Scala中,getter和setter分别叫做age和age_=例如:
val personA = new PersonAprintln("startAge=> " + personA.age)personA.age = 21println("endAge=> " + personA.age)
执行下面的命令:
Scalac PersonOps.scala\src\main\scala\tw\tw>javap -p PersonA.classCompiled from "PersonOps.scala"
然后会生成下面的内容:
public class tw.PersonA { private int age; public int age(); public void age_$eq(int); public tw.PersonA();}
正如你看到的那样,编译器创建了age
和age_$eq
,是因为JVM不允许在方法名中出现=
说明:在Scala中,getter和setter方法并非被命名为getXxx和setXxx,不过它们的用意是相同的。后面会介绍如何生成Java风格的getXxx和setXxx方法,以使得你的Scala类可以与Java工具实现互操作
这部分先不用搞太复杂,直接使用Java版本的getter/setter方法即可,如下面一个类:
class Student { private var age:Int = 0 def setAge(age:Int): Unit = { this.age = age } def getAge() = age}
测试如下:
scala> val s = new Student()s: Student = Student@1608bb5dscala> sres200: Student = Student@1608bb5dscala> s.getAge()res201: Int = 0scala> s.getAgeres202: Int = 0scala> s.setAge(18)scala> s.getAgeres204: Int = 18
官方关于getter/setter的知识内容非常多,入门的时候这些案例可以先不用管,先从Java的角度出来能够使用scala进行开发即可。
如果对属性使用了@BeanProperty
注解,那么就会自动生成getter/setter方法,但是需要注意的是,其并没有隐藏原来的属性,也就是说原来的属性还是可以直接访问的,并且其不可以使用private进行修饰。
看下面一个例子:
import scala.beans.BeanPropertyclass Student { @BeanProperty var age:Int = 0 }
测试如下:
scala> var s = new Students: Student = Student@46482990scala> s.getAge()res205: Int = 0scala> s.setAge(18)scala> s.getAge()res207: Int = 18scala> s.ageres208: Int = 18
上面啰嗦了很多,其实直接用下面的代码来进行说明就OK了:
/** * scala面向对象第一章 * 关于对象的构造 * 类的构造(和java一样) * * 要运行一个scala的程序,不能在class来执行,需要在object中执行 * 你可以将这个object中的所有的字段、成员,都作为java中的静态的成员对待 * * 在创建scala函数的时候,如果函数空参,我们可以在创建的时候省略掉这个(),但是在访问的时候也就不能使用带()的方式 * 反之我们既可以使用带(),也可以使用不带()的方式进行调用 * ab.foreach(println) * * 为什么我们要在javabean对字段创建对应的getter和setter * 带getter和setter的属性 * 就是为了程序的安全性? * 屏蔽一些不合法的操作,提高程序的健壮性 */object _01ClazzFieldsOps { def main(args: Array[String]): Unit = { val person:Person = new Person() person.increment() println(person.currentAge()) println(person.currentAge) val stu = new Student// stu.age = -1 stu.setAge(-4) stu.getName val e = new Employee }}class Person { private var age:Int = 0 //创建一个类型为Int的私有化成员 def increment(): Unit = { age += 1 } def currentAge() = age}class Student { private var age:Int = 15 private var name:String = "刘向前" def setAge(a:Int):Unit = { if(a < 1) { throw new RuntimeException(s"你们家的孩子才是($a)岁呢") } age = a } def getAge = age def getName = name}class Employee { @BeanProperty var age:Int = 5}
关于构造器的说明和使用,直接看下面的测试代码就可以了,非常简洁:
package cn.xpleaf.bigdata.p2.constructor/** * scala中的类的构造器说明 * scala类的构造器分为主构造器和辅助构造器 * 其构造方式不同于java中的构造方式,public 类名(参数列表){},在scala中的构造器如何定义? * scala中把类名后面的一对{}括起来的内容称为主构造器的函数体,默认的主构造器为空参构造器, * 如何定义一个有参的主构造器呢? * 就在类名后面写上函数的定义即可 * * 当主构造器满足不了我们的需求之后,我们就可以创建更多的辅助构造器来配合我们的业务,辅助构造器如何创建? * def this // 辅助构造器的函数名是this * 注意,在辅助构造中的第一句话,必须是调用该类的主构造器或者其他辅助构造器,this(参数) * * 在一个类中只能有一个主构造器,可以有若干辅助构造器,在辅助构造器的第一句话,调用this * */object _02ConstructorOps { def main(args: Array[String]): Unit = { val p = new Person // p.show() println("=================================") val stu = new Student("前向刘", 17) stu.show() println("=================================") val s = new Student println("=================================") val s1 = new Student(true) }}class Person { private var name:String = "刘向前" private var age:Int = 18/* def Person(n:String, a:Int): Unit = { name = n age = a println("这是scala中的构造器吗?") } def Person(): Unit = { println("这是scala中的构造器吗?") }*/ println("这是scala中的构造器吗?") def show() = println(s"name is $name and age is $age")}class Student(var name:String, var age:Int) { def this() { this("刘银鹏", 25) println("this is 辅助构造器") } private var married:Boolean = false def this(isMarried:Boolean) { this() married = isMarried println(s"this($isMarried) 是另外一个构造器") } println("这是scala中的构造器吗?") def show() = println(s"name is $name and age is $age") // show() // 类构造时就会执行该方法,属性name和age也是默认有的,因为在主构造器中有}
直接看下面的一个完整案例:
package cn.xpleaf.bigdata.p2.inner/** * 事物的内部还包含着事物,被包含的事物不能使用非常简单的成员变量来描述,只能使用更为复杂的结构去描述, * 这个时候就用我们的内部类去定义 * * 当多个变量重名的时候,遵循一个原则:局部优先 public class InnerClassOps { public static void main(String[] args) { Outer.Inner i = new Outer().new Inner(); i.show(); } } class Outer { private int x = 5; class Inner { private int x = 6; public void show() { int x = 7; System.out.println("Inner show: " + x); } } } this关键字,是本类的引用,当前类的实例的引用 外部类的引用使用外部类名.this scala同样提供了一种较为简洁的写法,就是在我们的最外层大括号里写一个引用名称outer => 在内部类中需要调用外部类的成员的时候,直接使用outer.成员代替外部类名.this */object _03InnerClassOps { def main(args: Array[String]): Unit = { val outer = new Outer val inner = new outer.Inner inner.show() }}class Outer { o => private val x = 5 class Inner { i => private var x = 6 def show(): Unit = { val x = 7 println("Inner show: " + this.x) // 6 println("Inner show: " + i.x) // 6 println("Inner show: " + Outer.this.x) // 5 println("Inner show: " + o.x) // 5 } }}
转载于:https://blog.51cto.com/xpleaf/2105702