写在前面
最近把Scala一些基础的东西简单复习一下,然后顺便也记录下来,后面就可以直接看自己的笔记了。当然,也希望能够帮到一些刚入门的小伙伴~
如果有什么错误的地方,欢迎指正~ 我也还在不断的学习中,大家一起加油!
01 Range & to & until & 循环
其实 to until 底层也是调用的Range方法
until 的定义
/**
* @param end The final bound of the range to make.
* @return A [[scala.collection.immutable.Range]] from `this` up to but
* not including `end`.
*/
def until(end: Int): Range = Range(self, end)
其实就是:[) 左闭右开 ,不过需要注意是 immutable.Range ,不可变的集合
简单demo:
两种写法,
1.until(10) // 输出 1,2,3...,9
1 until 10
在实际开发过程中,我们可能会用来循环某一个数组的时候使用到
to 的定义
/** like `until`, but includes the last index */
/**
* @param end The final bound of the range to make.
* @return A [[scala.collection.immutable.Range]] from `'''this'''` up to
* and including `end`.
*/
def to(end: Int): Range.Inclusive = Range.inclusive(self, end)
其实就是: [] 左闭右闭 ,不过需要注意也是 immutable.Range ,不可变的集合
简单demo:
两种写法,
1 to 10 // 输出 1,2,3...,10
1.to(10)
Range 的定义
val Range = scala.collection.immutable.Range
/** Make a range from `start` until `end` (exclusive) with given step value.
* @note step != 0
*/
def apply(start: Int, end: Int, step: Int): Range = new Range(start, end, step)
Range(1 ,10 ,2) // 1 到 10 ,步长2
循环 简单演示
for (i <- 0 until 10){
println(i) // 输出:0,1,2,...,9
}
for (i <- 0 until 10 if i%2==0){
println(i) // 输出:0,2,4,6,8
}
// 循环数组的值
Array("留歌","石石石","ZKKKK").foreach(println(_))
Array("留歌","石石石","ZKKKK").foreach(x => println(x))
02 函数/方法
我后面统一就叫做方法吧,我想任何一门编程语言都有这个玩意把,不管你是python(非编译解释型),Java(混合型),shell(脚本语言)…还是这里的Scala(函数式)。
方法的基本定义:
参数列表
def 函数名(x:Int, y:String ....) : 返回值类型 = {
。。。
xxx // 最后一行代码 作为返回值
}
讲真,有点python的感觉
2.1 来一个demo:
def add(x:Int, y:Int) :Int = {
x+y
}
println(add(1,2)) // 输出:3
2.2 上面这个是一个有返回值 Int 的方法,你也可以没有返回值,类似Java的void,如下:
def sayHello() : Unit = {
println("Hello 这个方法是没有返回值的~")
}
Tips: A method with return type
Unit
is analogous to a Java method which is declaredvoid
.
其实这里的Unit 是可以缺省的,会自动进行类型推导的。
这里在调用的时候,可以有以下两种方式:
sayHello()
sayHello // 当调用的方法没有入参时,可以省略括号(有一种方法除外。即带默认参数的方法)
上面的都是常规的一些,接下来是比较特殊的一些
带默认参数的方法
def loadSparkConf(fileName: String = "spark-default.conf") = {
println(fileName)
}
loadSparkConf("spark-liuge.conf")
loadSparkConf() // 这里必须要带上括号,【就这个比较特殊,其余的不是默认参数的 可以省略括号的】
带命名参数的方法(不推荐)
def teacher(spark:String, java:String) = {
println(s"spark teacher is ${spark}, java teacher is ${java}")
}
teacher("留歌", "石石石")
println("#########################")
teacher(java= "石石石", spark = "留歌")
带变长参数的方法(重点掌握)
def sum(a:Int, b:Int)={
a+b
}
println(sum(1,2))
// 思考:上面这个加入是3个参数求和咋办?多个呢? ==> 变长参数
def sum2(nums:Int*): Int ={
var result = 0
for (num <- nums) {
result += num
}
result
}
println(sum2(1,2,3,4))
重点( :_* 这个符号这个符号可以将不可变参数 转为可变参数)
// 特殊的
println( sum2(1.until(11) :_* ) ) // :_* 这个符号可以将不可变参数 转为可变参数,55
// :_* 也可以把数组Array("","","")转变为一个可变参数 传递给可变参数的方法
println( sum2(Array(1,2,3,4):_*) )
03 属性 & 类 & 对象
这里的类与属性的概念其实和Java是一样的,要想使用一个类,必须要先实例化对象出来,可以直接new ,得到这个对象之后就可以调用其 非private的属性和方法 了。
在Java中我们常常实例化类的时候分为: 无参构造方法 和 带参数的构造方法 ,这里也不例外
3.1 类的构造方法是没有参数的
// 定义一个类,注意:这个类的构造方法是没有参数的
class People {
// 定义属性
var name:String = _ // _下划线表示占位符
val age:Int = 10
private[this] val gender = "M" // private[this] 修饰的只能在本类中使用,外部无法使用
// 定义方法
def eat() :String = {
name + " eat ..."
}
}
3.2 带参数的构造方法
注意这里带参构造方法的写法
主构造器
// 主构造函数,带 name & age 两个参数 ,而且在new的时候必须要传的
class Girl(val name:String,val age:Int) {
var city:String = "深圳"
}
Girl类 实例化对象出来:
val girl = new Girl("苍老师",18)
println(girl.name + " : " + girl.age + " : " + girl.city )
这里发现没有,构造方法中的参数 以及 类中非private属性 都能当做 类对象的属性 直接使用
当然了,提到了构造方法,怎能不提一下重载呢?
重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
附属构造器
这里我们也可以对上面Girl类的主构造器进行重载,得到附属构造器
接着上面的代码,写一个附属构造器
class Girl(val name:String,val age:Int) {
var city:String = "深圳"
// 附属构造函数1
var phoneNumber = ""
def this(name:String, age:Int, phoneNumber:String) {
this(name, age) //调用 主构造器
this.phoneNumber = phoneNumber
}
// 附属构造函数2
var address = ""
def this(name:String, age:Int, phoneNumber:String, address:String) {
this(name, age, phoneNumber) //调用 其他附属构造器
this.address = address
}
}
注意:第一行必须调用主构造器 或 其他附属构造器
实例化:
val girlfushu1 = new Girl("吉老师",21,"15710000000")
println(girlfushu1.name + " : " + girlfushu1.age + " : " + girlfushu1.phoneNumber )
val girlfushu2 = new Girl("花老师",21,"15710000000","深圳市南山区科学园")
println(girlfushu2.name + " : " + girlfushu2.age + " : " + girlfushu2.phoneNumber + " : " +girlfushu2.address)
这样就可以选择 合适自己参数个数的 构造器进行实例化对象了,其实感觉就是多态
多态是同一个行为具有多个不同表现形式或形态的能力。
04 继承 & 抽象类
4.1 继承
概念和java类似,使用关键字extends
继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
我们写一个类去继承上面的Girl 类:
class Shishishi(name: String, age :Int, val major :String) extends Girl(name, age){
println(" Shishishi enter")
def eat(): Unit ={
println("eat ....")
}
// 重写父类中已经有的方法时候,需要添加 override 修饰符
override def toString = "shishishi to string"
println(" Shishishi leave")
}
注意两点:
1.继承的时候,当创建子类对象的时候,会先去调用父类的构造方法;
2.重写父类中已经有的方法时候,需要添加 override 修饰符
实例化
val shishishi = new Shishishi("石石石",23,"计算机科学")
println(shishishi.name + " : " + shishishi.age + " : " + shishishi.major)
println(shishishi.toString)
4.2 抽象类
类中有一个或多个方法/属性没有实现 :只有定义,没有实现
是不能直接new的,必须要通过 实现了该抽象类的属性/方法的子类 才能使用
子类重写父类中的方法或属性不需要使用override 【可要可不要】
简单demo:
object AbstractApp {
def main(args: Array[String]): Unit = {
val dog = new Dog
dog.speak
}
}
abstract class Animal{
var name:String
var age:Int
def speak
}
class Dog extends Animal{
override var name: String = "小奶狗"
override var age: Int = 1
override def speak: Unit = {
println("~~~~~···说说说话")
}
}
未完待续~