一、用IDEA编写scala语言
1、安装
首先安装scala的msi,,,scala-2.11.8.msi
看一下环境变量有没有添加(参照上)
2、下载Scala插件
- 搜索scala
- 重启idea,创建scala项目:
- 此时src为灰色
设置src目录为源码目录
在src目录上右键,选择Mark Directory as---->Sources root
但是我们右键创建文件时,没有scala的相关文件,是因为idea没有scala的sdk,需要添加
3、测试是否可用
package com.doit.scala.class10
object TestClass10 {
def main(args: Array[String]): Unit = {
println("Hello Scala!!")
}
}
能打印出来则成功
二、面向对象编程
- scala是面向对象,也是面向过程的。就是可以传函数。
- 在java中,要想传函数,一般就是封装到一个类里,传一个匿名内部类。scala的函数是一级成员,可以定义一个函数,传到另外一个函数里
1、类
1)定义一个简单的类
//定义类,包含field以及方法
package com.doit.scala.class10
class HelloWorld_10_2 {
private var name = "leo"
def sayHello() { print("Hello, " + name) }
def getName = name
}
- 函数:类外边定义的def
- 方法:类内定义的def
- 注意: 如果定时的def后的方法名没加(),在调用的时候就不能加();定义def的方法名加了()调用时,可以加()也可以不加()
//创建类的对象,并调用其方法
object TestClass10 {
def main(args: Array[String]): Unit = {
val helloWorld = new HelloWorld_10_2
helloWorld.sayHello()
// 也可以不加括号,如果定义方法时不带括号,则调用方法时也不能带括号
print(helloWorld.getName)
}
}
2)getter与setter
- 定义不带private的var field,此时scala生成的面向JVM的类时,会定义为private的name字段,并提供public的getter和setter方法
- 而如果使用private修饰field,则生成的getter和setter也是private的
- 如果定义val field,则只会生成getter方法
- 如果不希望生成setter和getter方法,则将field声明为private[this]
class Student_10_3 {
var name = "leo"
}
// 调用getter和setter方法,分别叫做name和name_ =
object TestClass10 {
def main(args: Array[String]): Unit = {
val leo = new Student_10_3
leo.name = "leo 1"
print(leo.name)
}
}
3)自定义getter与setter
- 如果只是希望拥有简单的getter和setter方法,那么就按照scala提供的语法规则,根据需求为field选择合适的修饰符就好:var、val、private、private[this]
- 如果希望能够自己对getter与setter进行控制,则可以自定义getter与setter方法
- 自定义setter方法的时候一定要注意scala的语法限制,签名、=、参数间不能有空格
class Student_10_4 {
private var myName = "leo "
def name = "your name is " + myName
//注意:name_与=之间没有空格
def name_=(newValue: String): Unit = {
println("you cannot edit your name !!!")
}
}
//编写测试类
object TestClass10 {
def main(args: Array[String]): Unit = {
val leo = new Student_10_4
print(leo.name)
leo.name = "leo 1 "
}
}
4) 仅暴露field的getter方法
// 如果不希望field有setter方法,则可以定义为val,但是此时就再也不能更改field的值了
// 但是如果希望能够仅仅暴露出一个getter方法,并且还能通过某些方法更改field的值,那么需要综合使用private以及自定义getter方法
// 此时,由于field是private的,所以setter和getter都是private,对外界没有暴露;自己可以实现修改field值的方法;自己可以覆盖getter方法
class Student_10_5 {
private var myName = "wang"
def updateName(newName: String) {
if(newName == "wang 1") myName = newName
else print("not accept this new name !!!")
}
def name = "your name is " + myName
}
//测试类
object TestClass10 {
def main(args: Array[String]): Unit = {
val wang = new Student_10_5
println(wang.name)
wang.updateName("wang1")
}
}
5) private[this]的使用
- 如果将field使用private来修饰,那么代表这个field是类私有的,在类的方法中,可以直接访问类的其他对象的private field
class Student_10_6_1 {
private var myAge = 0
def age_=(newValue: Int): Unit ={
if (newValue > 0) myAge = newValue
else print("illegal age !")
}
def age = myAge
def older(s: Student_10_6_1) = {
myAge > s.myAge
}
}
//测试类
object TestClass10 {
def main(args: Array[String]): Unit = {
val s1 = new Student_10_6_1
s1.age = 19
val s2 = new Student_10_6_1
s2.age = 11
s1.older(s2)
}
}
- 这种情况下,如果不希望field被其他对象访问到,那么可以使用private[this],意味着对象私有的field,只有本对象内可以访问到
class Student_10_6_2 {
private[this] var myAge = 0
def age_=(newValue: Int) {
if (newValue > 0) myAge = newValue
else print("illegal age!")
}
def age = myAge
def older(s: Student_10_6_2) = {
myAge > s.myAge
}
}
//测试类
object TestClass10 {
def main(args: Array[String]): Unit = {
val s1 = new Student_10_6_2
s1.age=19
val s2 = new Student_10_6_2
s2.age =11
s1.order(s2)
}
}
因为在olders方法中,调用了s.myage,但是,之前定义个字段是private[this],只有当前类可用
6)Java风格的getter和setter方法
- Scala的getter和setter方法的命名与java是不同的,是field和field_=的方式
- 如果要让scala自动生成java风格的getter和setter方法,只要给field添加@BeanProperty注解即可
- 此时会生成4个方法,name: String、name_=(newValue: String): Unit、getName(): String、setName(newValue: String): Unit
import scala.beans.BeanProperty
class Student_10_7_1 {
@BeanProperty var name: String=_
}
//测试类
object TestClass10 {
def main(args: Array[String]): Unit = {
val s = new Student_10_7_1
s.setName("wang")
println(s.getName)
}
}
import scala.beans.BeanProperty
class Student_10_7_2 (@BeanProperty var name: String)
//测试类
object TestClass10 {
def main(args: Array[String]): Unit = {
val s1 = new Student_10_7_2("wang")
println(s1.getName)
}
}
7)辅助constructor
- Scala中,可以给类定义多个辅助constructor,类似于java中的构造函数重载
- 辅助constructor之间可以互相调用,而且必须第一行调用主constructor
class Student_10_8 {
private var name = ""
private var age = 0
def this(name: String) {
// 辅助constructor之间可以互相调用,而且必须第一行调用主constructor
this()
this.name = name
}
def this(name: String,age: Int){
//可以直接调用上边定义的辅助构造函数
this(name)
this.age = age
}
}
//测试类
object TestClass10 {
def main(args: Array[String]): Unit = {
val s1 = new Student_10_8()
val s2 = new Student_10_8("wang")
println(s2.name)
val s3 = new Student_10_8("wang",30)
println(s3.name)
}
}
8)主constructor
- Scala中,主constructor是与类名放在一起的,与java不同
- 而且类中,没有定义在任何方法或者是代码块之中的代码,就是主constructor的代码,这点感觉没有java那么清晰
class Student_10_9_1 (val name: String, val age: Int){
println("your name is " + name + ", your age is " + age)
}
// 主constructor中还可以通过使用默认参数,来给参数默认的值
class Student_10_9_2 (val name: String = "leo", val age: Int = 30){
println("your name is " + name + ", your age is " + age)
}
object TestClass10 {
def main(args: Array[String]): Unit = {
val s1 = new Student_10_9_1("liu", 33)
val s2 = new Student_10_9_2()
}
}
9)内部类
- Scala中,同样可以在类中定义内部类;但是与java不同的是,每个外部类的对象的内部类,都是不同的类
import scala.collection.mutable.ArrayBuffer
class Class_10_10 {
class Student(val name: String) {}
val students = new ArrayBuffer[Student]
def getStudent(name: String) = {
new Student(name)
}
}
object TestClass10 {
def main(args: Array[String]): Unit = {
val c1 = new Class_10_10
val s1 = c1.getStudent("leo")
c1.students += s1
}
}
object TestClass10 {
def main(args: Array[String]): Unit = {
val c1 = new Class_10_10
val s1 = c1.getStudent("leo")
c1.students += s1
val c2 = new Class_10_10
val s2 = c2.getStudent("leo")
c1.students += s2
}
}
/**
Error:(59, 19) type mismatch;
found : c2.Student
required: c1.Student
c1.students += s2
**/