类、对象
引言
\quad \quad 在Java中,一个类要能独立运行,那么必须具有静态的main方法,如下所示。
public static void main(String[] args) {
...
}
\quad \quad 在Scala中,为了运行一个Scala程序,你必须定义一个Scala对象并为其定义一个main方法:
-
在IDEA中创建项目,并创建一个Object(main方法必须放在Object中)
-
添加 main 方法。
快捷方法
:IDEA中,输入main
然后按Enter
键即可补全 -
在 main 方法中代码运行得出结果
object hello_scala {
def main(args: Array[String]): Unit = {
println("hello,scala")
}
}
结果:
-
Scala中的Object相当于java中的静态类,在其上可以定义静态的方法。Scala允许一个类定义自己的“伴生对象”(Companion Object),它们具有相同的名字,必须位于同一个文件中,并且可以互相引用各自的私有成员。Scala的Object也可以独立存在。如果一个Scala Object没有伴生对象,我们称之为“独立对象”(Standardalone Object),反之,对象和类互为友元。
-
上述代码main方法中的参数args是从命令行中传入的参数列表,具体用法和java类似。
1、类(class)
\quad \quad 类是对象的模板,主要由方法和属性构成。
- 类是对象的抽象,而对象是类的具体实例。类是抽象的,不占用内存,而对象是具体的,占用存储空间。类是用于创建对象的蓝图,它是一个定义包括在特定类型的对象中的方法和变量的软件模板。
1.1 定义类
语法:
class 类名{
//属性
//成员方法(使用def定义)
}
例子
class User{
// 属性
var name : String ="xiaoming"
// 方法
def sayHello(name:String):String={
"hello"+name}
}
1.2 访问修饰符
\quad \quad
和Java一样,scala也可以通过访问修饰符,来控制类中属性和成员方法是否可以被访问。可以在成员前面添加private/protected
关键字来控制成员的可见性。但在scala中,没有public关键字,任何没有被标为private或protected的属性或成员都是公共的。
- 当类的属性是公共的实时可以通过“对象.属性” 直接调用,当属性是private私有时,只能在类中使用,而不能通过“对象.属性” 直接调用,这时就需要该字段的getter和setter进行访问。
- scala中的getter和setter方法是通过value和value_=进行实现的,以下是具体的实现
object GetterSetterTest {
def main(args: Array[String]): Unit = {
var person = new Person1();
println(person.myName)
person.myName_=("lisi")
println(person.myName)
}
}
class Person1{
private var name:String="zhangsan";//
def myName=name;//读操作
def myName_=(name:String): Unit ={ //修改操作
this.name = name;
}
}
1.3 创造类
也称创造对象
语法: new
类名
var person = new People()
1.4 利用类中的方法运行程序
object hello_scala {
def main(args: Array[String]): Unit = {
val person = new User()
println(person.sayHello("xiaohong"))
}
}
class User{
// 属性,这里设置变量,初始化为小明,只为了占位可更改,
var name : String ="xiaoming"
// 方法
def sayHello(name:String):String={
"hello"+name}
}
结果:
1.5 类的构造器
\quad \quad 类似于java重载的构造方法,在Scala类中有一个主构造器(Primary Constructor)和若干个辅助构造器。当创建对象的时候,会自动调用类的构造器。之前学的都是默认构造器,我们接下来要学习如何自定义构造器。
1.5.1 主构造器
\quad \quad
跟在类名后面的就叫做主构造器
语法
class 类名(var/val 参数名:参数类型,var/val 参数名:参数类型,...){
// 构造代码块
}
- 主构造器的参数列表是直接定义在类名后面,添加了val/var表示直接通过主构造器定义成员变量
- 构造器参数列表可以指定默认值
- 创建实例,调用构造器可以指定字段进行初始化
- 整个class中除了字段定义和方法定义的代码都是构造代码
例子:
object gouzaoqi {
def main(args: Array[String]): Unit = {
// 创建对象
val zhangsan = new Person("张三",20)
//println(zhangsan.name+zhangsan.age)
}
}
// 定义类的主构造器
class Person(var name:String,var age:Int){
println("调用主构造器")
}
- 只创建一个对象,不输出任何内容时,只会输出代码块的内容
object gouzaoqi {
def main(args: Array[String]): Unit = {
// 创建对象
val zhangsan = new Person("张三",20)
println(zhangsan.name+zhangsan.age)
}
}
// 定义类的主构造器
class Person(var name:String,var age:Int){
println("调用主构造器")
}
结果:
应用场景:
- 主构造器的作用范围是整个类体,属性和方法仅仅只是生命并不会立即执行,而对于其他内容,在每一次创建对象时都会执行。
- 当多个需求中有多个共同的部分时,可将共同部分写在代码块中,每次只创建对象即可
1.5.2 辅助构造器
\quad \quad 在scala中,除了定义主构造器外,还可以根据需要来定义辅助构造器。例如:允许通过多种方式,来创建对象,这时候就可以定义其他更多的构造器。我们把除了主构造器之外的构造器称为辅助构造器。
语法
- 定义辅助构造器与定义方法一样,也使用def关键字来定义
- 这个方法的名字为this
- 辅助构造器的第一行代码,必须要调用主构造器或者其他辅助构造器
def this(参数名:参数类型,参数名:参数类型){
// 第一行代码必须以调用主构造器或其他辅助构造器为开始
//构造器代码
}
例子:
- 构造辅助构造器,并调用使用
object gouzaoqi {
def main(args: Array[String]): Unit = {
// 创建对象
//val zhangsan = new Person("张三",20)
//println(zhangsan.name+zhangsan.age)
val lisi = new Person("lisi",18,"male")
println(lisi.name+":"+lisi.age+":"+lisi.gender)
}
}
// 定义类的主构造器
class Person(var name:String,var age:Int){
//println("调用主构造器")
//定义辅助构造器
var gender:String=_
def this(name:String,age:Int, gender:String){
this(name,age)
this.gender=gender
}
}
结果:
- 创建两个对象,一个调用主构造器,一个调用辅助构造器
object gouzaoqi {
def main(args: Array[String]): Unit = {
// 创建对象
val zhangsan = new Person("张三",20)
println(zhangsan.name+zhangsan.age)
val lisi = new Person("lisi",18,"male")
println(lisi.name+":"+lisi.age+":"+lisi.gender)
}
}
// 定义类的主构造器
class Person(var name:String,var age:Int){
println("调用主构造器")
//定义辅助构造器
var gender:String=_
def this(name:String,age:Int, gender:String){
this(name,age) //第一行必须调用主构造器或其他辅助构造器
this.gender=gender
}
}
结果:
2、对象
\quad \quad Scala中没有java的static关键字,但可以试用object实现等同效果目的。使用object修饰的类都是静态类也可以理解成对象 ,里面的定义的内容都是静态的可以直接用不需要new。
2.1 单例对象(object)
\quad \quad scala中没有Java中的静态成员,我们想要定义类似于Java的static变量、static方法,就要使用到scala中的单例对象——object。
定义单例对象
-
单例对象表示全局仅有一个对象(类似于Java static概念)
-
定义单例对象和定义类很像,就是把class换成object
-
在object中定义的成员变量类似于Java的静态变量
-object定义的成员变量可以直接引用,而不用new
例子:
object 对象名 {
// 属性,下划线_表示占位符
val/var 参数名:参数类型=_
// 成员方法
def 方法名(参数名:参数类型):返回类型={
// 代码块
}
}
- 声明单例对象只需要将类声明为object即可。
- object单例对象中的成员都是静态的。
例子:
object duixiang {
def main(args: Array[String]): Unit = {
println(User.sayHello("xiaohong"))
}
}
object User{
var name : String ="xiaoming"
// 方法
def sayHello(name:String):String={
"hello"+name}
}
2.2 伴生对象和伴生类
\quad \quad 一个class和object具有同样的名字。这个object称为伴生对象,这个class称为伴生类
- 伴生对象必须要和伴生类一样的名字
- 伴生对象和伴生类在同一个scala源文件中
- 伴生对象和伴生类可以互相访问private属性
- private [this] 访问权限
- 如果某个成员的权限设置为 private[this],表示只能在当前类中访问。伴生对象也不可以访问。此时,转为private属性即可
例子:
object duixiang {
def main(args: Array[String]): Unit = {
val lisi=new User()
lisi.save()
//println(User.sayHello("xiaohong"))
}
}
// 伴生类和伴生对象
class User{
def save()={
println(s"${User.name}:保存客户")
}
}
object User{
var name : String ="xiaoming"
// 方法
def sayHello(name:String):String={
"hello"+name}
}
- 伴生类中可以调用伴生对象方法
2.3 apply 方法
- 伴生对象中的apply方法,实际上是一个工厂方法,用以构建伴生类。
- 目的为了调用方法/函数方便
语法
定义
object 伴生对象名{
def apply(参数名:参数类型,参数名:参数类型...)=new 类(...)
}
创建对象
伴生对象名(参数1,参数2...)
例子:
object Apply_demo {
def main(args: Array[String]): Unit = {
// 使用伴生对象来创建对象
val zhangsan=Person("zhangsan",18)
println(zhangsan.name)
println(zhangsan.age)
}
}
class Person(var name:String="",var age:Int=2)
//
object Person{
def apply(name:String,age:Int)=new Person(name,age)
}
2.4 main方法
\quad \quad Scala和Java一样,如果要运行一个程序,必须有一个main方法。而在Java中main方法是静态的,而在scala中没有静态方法。在scala中,这个main方法必须放在一个单例对象中。
定义main方法
语法:
def main(args: Array[String]): Unit = {
// 方法体
}
例子:
object Apply_demo {
def main(args: Array[String]): Unit = {
println("hello")
}
}
2.5 实现App Trait 来定义入口
\quad \quad 创建一个object,继承自App Trait(特质),然后将需要编写在main方法中的代码,写在object的构造方法体内。
语法
object 对象名 extends App {
// 方法体
}
例子:
object hello extends App {
println("hello")
}
3、继承
\quad \quad Scala语言是支持面向对象编程的,我们也可以使用scala来实现继承,通过继承来减少重复代码。
定义
- scala和Java一样,使用
extends
关键字来实现继承 - 可以在子类中定义父类中没有的字段和方法,或者重写父类的方法
- 子类继承父类的时候,属性中如果有父类的属性,不用加
val/var
;但是父类没有的属性,必须加val/var
,否则外面无法访问。 - 类和单例对象都可以从某个父类继承
语法
class/object 子类 extends 父类 {
..
}
示例 | 类继承
object jicheng {
def main(args: Array[String]): Unit = {
val p1 = new student()
println(p1.name+" : "+p1.age)
}
}
class Person{
var name = "super"
def getname = this.name
}
class student extends Person{
var age=18
}
结果:
示例2 | 单例对象继承类
- 创建一个Student单例对象,让单例对象Person类
- 设置单例对象的名字为"张三"
object jicheng {
def main(args: Array[String]): Unit = {
println(student.name+" : "+student.age)
}
}
class Person{
var name = "super"
def getname = this.name
}
object student extends Person{
name="张三"
var age=18
}