版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
传送门:大数据系列文章目录
目录
如何使用IDEA创建scala项目
创建普通的scala项目
接下来, 即可创建包结构, 编写scala代码
创建scala的maven项目
- 创建一个maven项目, 添加如下依赖
<properties>
<project.build.source.Encoding>UTF-8</project.build.source.Encoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>2.12.11</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/main/scala</sourceDirectory>
<testSourceDirectory>src/test/scala</testSourceDirectory>
<plugins>
<!-- Scala编译插件-->
<plugin>
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<version>2.15.2</version>
<executions>
<execution>
<id>scala-compile-first</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<includes>
<include>**/*.scala</include>
</includes>
</configuration>
</execution>
<execution>
<id>scala-test-compile</id>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- maven编译插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
- 分别在src/main下构建scala目录(创建完文件夹是白色的,往下看)
- 点击刷新, 将scala目录变更为source目录
刷新完的效果:
- 编写代码进行书写即可
scala的中普通类
创建类也是使用class的关键词来构建的
创建普通类:
package com.lwh
/**
* @author lwh
* @date 2022/11/17
* @description
**/
class Person {
// 注意: 在普通类中定义成员变量的时候, 如果使用val定义, 必须要进行赋值,
// 如果使用 var定义, 可以使用 _ 替代 , 此时赋上默认值
// 在类中不存在 Public scala认为 只要不带权限修饰符的都是 public , 支持的权限符号: private || protected
//private val name:String = "张三"
val name:String = "张三"
var age:Int = 20
var birthday:String = _
def eat(name:String): Unit = {
println(name + "饿了.....")
}
}
定义main方法: main必须放置在Object类
package com.lwh
/**
* @author lwh
* @date 2022/11/17
* @description
**/
object MainTest {
def main(args: Array[String]): Unit = {
//1. 创建对象:
val perosn1:Person = new Person()
// 说明 如果 无参数, () 是可以省略的
val perosn2:Person = new Person
// 获取成员变量
println(perosn1.name)
println(perosn1.age)
println(perosn1.birthday)
// 设置成员变量: 只能设置被 var修饰
// perosn1.name = "李四" name是被 val修饰 编译直接报错
perosn1.age = 30
perosn1.birthday = "2020-10-10"
println(perosn1.age)
println(perosn1.birthday)
// 调用方法:
perosn1.eat("老王")
}
}
构造器:
在scala中普通类也是存在构造方法的, 默认情况下都是会有一个无参构造方法, 在scala即使有了有参构造, 无参依然存在的
在scala中将构造分为两大类:
-
主构造: 直接放置在类的后面, 通过括号来执行构造器的参数即可
-
主构造器的格式:
class 类名(var/val 参数名:类型 = 默认值, var/val 参数名:类型 = 默认值){
// 构造代码块
}
说明:
- 主构造器的参数列表是直接定义在类名后面,添加了val/var表示直接通过主构造器定义成员变量
- 构造器参数列表可以指定默认值
- 创建实例,调用构造器可以指定字段进行初始化
- 整个class中除了字段定义和方法定义的代码都是构造代码
- 相关的操作
- 辅助构造器:
- 格式:
def this(参数名:类型, 参数名:类型) {
// 第一行需要调用主构造器或者其他构造器
// 构造器代码
}
- 辅助构造器的第一行代码,必须要调用主构造器或者其他辅助构造器
创建对象:
//2. 基于辅助构造器, 创建person对象
val person3 = new Person(Array("李四"))
println(person3.name)
val person4 = new Person(List("王五"))
println(person4.name)
scala的单例对象
在scala中是不支持static修饰的, 所以在普通类中创建的成员变量和成员的方法都是非静态的, 那么如果我们想构建静态的变量或者静态的方法就得需要scala提供的单例对象
在单例对象中定义的成员变量和成员方法都是静态的, 可以直接通过类名调成员即可。
如何构建单例对象: 与构建普通类类似的, 只是将 class修改为Object即可
相关的操作:
- 创建单例对象:
package com.lwh
/**
* @author lwh
* @date 2022/11/17
* @description
**/
object Student {
val name: String = "李四同学"
var age: Int = 20
val address: String = "北京"
def study(name: String): Unit = {
println(name + "说:我要努力好好学习scala")
}
}
- 使用单例对象
package com.lwh
/**
* @author lwh
* @date 2022/11/17
* @description
**/
object StudentTest {
def main(args: Array[String]): Unit = {
println(Student.address)
Student.study("老王")
}
}
单例对象一般被用于构建工具类:
需求
- 编写一个DateUtil工具类专门用来格式化日期时间
- 定义一个方法,用于将日期(Date)转换为年月日字符串,例如:2030-10-05
package com.lwh
import java.text.SimpleDateFormat
import java.util.Date
/**
* @author lwh
* @date 2022/11/17
* @description
**/
object DateUtil {
private val dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
def format(date: Date): String = {
dateFormat.format(date)
}
}
使用工具类:
package com.lwh
import java.util.Date
/**
* @author lwh
* @date 2022/11/17
* @description
**/
object DateUtilTest {
def main(args: Array[String]): Unit = {
val dateStr: String = DateUtil.format(new Date)
println(dateStr)
}
}
main方法
在java中, 执行代码必须有主入口main , 同样对应scala也是需要的, 在java中main方法是静态的方法, 在scala中如果要使用main方法, 那么必须将其定义在单例对象才可以
object Main5 {
def main(args:Array[String]) = {
println("hello, scala")
}
}
除了直接显现使用main方法, scala还支持其通过继承一个特质来完成main方法的编写
object 单例对象名 extends App {
// 方法体
}
package com.lwh
import java.util.Date
/**
* @author lwh
* @date 2022/11/17
* @description
**/
object DateUtilAppTest extends App {
private val dateStr: String = DateUtil.format(new Date)
println(dateStr)
}
scala的伴生对象
伴生对象主要解决什么问题: 一个类中既有静态的成员 又有非静态的成员, 此时在scala中采用伴生对象来解决
使用伴生对象的操作条件:
一个class和object具有同样的名字。这个object称为伴生对象,这个class称为伴生类
- 伴生对象必须要和伴生类一样的名字
- 伴生对象和伴生类在同一个scala源文件中
- 伴生对象和伴生类可以互相访问private属性
示例
示例说明
- 编写一个CustomerService类,有一个save方法,打印
服务类名称:保存客户
-
编写一个CustomerService伴生对象,定义一个私有变量,用于保存服务类名称
-
创建CustomerService对象,调用save方法1
package com.lwh
/**
* @author lwh
* @date 2022/11/17
* @description
**/
//伴生类
class CustomerService {
// 在伴生类定义变量 或者 方法 都是非静态的
def save() = {
println(CustomerService.serviceName + "保存客户")
}
}
//伴生对象
object CustomerService {
// 在伴生对象中定义的变量或者方法 都是静态的
private val serviceName = "业务端"
}
- 操作伴生对象
package com.lwh
/**
* @author lwh
* @date 2022/11/17
* @description
**/
object CustomerServiceTest extends App {
private val service = new CustomerService
service.save()
}
目前存在一个问题: 伴生对象在创建的时候, 可以不使用new的方式, 但是经过测试发现, 无法实施 如何解决呢?
解决方法: 需要在伴生对象中重写 apply的方法, 那么这样的化,就可以直接不采用new的方式来构建对象了
package com.lwh
/**
* @author lwh
* @date 2022/11/17
* @description
**/
//伴生类
class CustomerService {
// 在伴生类定义变量 或者 方法 都是非静态的
def save() = {
println(CustomerService.serviceName + "保存客户")
}
}
//伴生对象
object CustomerService {
// 特别注意:
// 在重写apply方法适合, 如果空参, 一定带上 括号, IDEA快捷方式可能没有生产正确
def apply(): CustomerService = new CustomerService()
// 在伴生对象中定义的变量或者方法 都是静态的
private val serviceName = "业务端"
}
注意: 一旦在成员变量的添加 添加 private[this] 仅能在当前类中使用, 其他的类就无法使用, 即使是伴生类也不行
scala的继承
scala的继承基本与java的继承是一致的, 也是通过extends方式来继承, 同时也是单继承的操作, 在scala中我们既可以使用普通类来继承父类, 也可以使用单例对象来继承父类
在继承后, 相当于将父类的所有的成员变量和成员方法都继承了过来
相关的操作:
- 创建一个父类
package com.lwh
/**
* @author lwh
* @date 2022/11/17
* @description
**/
class Animal(var eatFood:String = "吃东西") {
def eat(name:String) = {
println(name + ":" + eatFood)
}
}
- 普通类继承父类
package com.lwh
/**
* @author lwh
* @date 2022/11/17
* @description
**/
class Dog extends Animal {
// override 表示是重写方法
// super 调用父类的方法
override def eat(name: String): Unit = {
// 先调用父类的方法
super.eat(name)
println("狗吃骨头.....")
}
def work() = {
println("狗能看门")
}
}
- 单例对象继承父类
package com.lwh
/**
* @author lwh
* @date 2022/11/17
* @description
**/
object Cat extends Animal {
override def eat(name: String): Unit = {
super.eat(name)
println("猫吃鱼......")
}
}
- 使用操作
package com.lwh
/**
* @author lwh
* @date 2022/11/17
* @description
**/
object AnimalTest extends App {
private val dog = new Dog
dog.eat("哈士奇")
dog.work()
println(Cat.eatFood)
Cat.eat("波斯猫")
}
scala中抽象类
scla的抽象类的操作与java是一致的
- 定义抽象类
package com.lwh
/**
* @author lwh
* @date 2022/11/17
* @description
**/
abstract class AnimalAbstract {
// 抽象的成员变量
var name:String
val age:Int
val address:String = "森林里"
// 抽象的方法:
def eat()
def run() = {
println("动物都是可以跑的.....")
}
}
- 实现抽象类
package com.lwh
/**
* @author lwh
* @date 2022/11/17
* @description
**/
class Tiger extends AnimalAbstract {
override val age: Int = 10
override var name: String = "东北虎"
override def eat(): Unit = {
println("老虎喜欢吃肉")
}
}
- 操作下
package com.lwh
/**
* @author lwh
* @date 2022/11/17
* @description
**/
object AnimalAbstractTest extends App {
private val tiger = new Tiger
tiger.run()
tiger.eat()
println(tiger.name +" "+tiger.age +" "+tiger.address)
}
scala中匿名内部类
package com.lwh
/**
* @author lwh
* @date 2022/11/17
* @description
**/
object AnimalInnerTest extends App {
// 假设目前使用cat的操作, 此操作只需要使用一次, 此时可以采用匿名内部类来实现, 因为如果直接构建一个实现类, 有点大材小用
val cat = new AnimalAbstract {
override var name: String = "加菲猫"
override val age: Int = 5
override def eat(): Unit = {
println("猫吃鱼..........")
}
override def run(): Unit = {
super.run()
println("猫在追耗子的时候, 可以跑起来")
}
}
cat.eat()
cat.run()
}