详解 Scala 面向对象相关知识

一、包

1. 作用

  • 区分相同名字的类
  • 当类很多时,可以很好的管理类
  • 控制访问范围

2. 声明语法

// 第一种:与 Java 一致,以 . 作为层级划分
package package_name

// 第二种:以 {} 作为层级划分
/*
	1. 一个源文件中可以声明多个 package
	2. 子包中的类可以直接访问父包中的内容,而无需导包
*/
package package_level1 {
    package package_level2 {
    	...
	}
}

3. 命名规则

  • 只能包含数字、字母、下划线,但不能用数字开头,也不要使用关键字
  • 一般按照 com.公司名.项目名.业务模块名 划分层级
package com {
    import com.tencent.Inner //父包访问子包需要导包
    object Outer {
        val out: String = "out"
        def main(args: Array[String]): Unit = {
        	println(Inner.in)
    	}
    }
    
    package tencent {
        object Inner {
            val in: String = "in"
            def main(args: Array[String]): Unit = {
            	println(Outer.out) //子包访问父包无需导包
            }
        }
    }
}

package com {
	package alibaba {
        
    }
}

4. 包对象

  • 概念:在 Scala 中可以为每个包定义一个与包同名的包对象,定义在包对象中的成员,可以作为其对应包下所有 class 和 object 的共享变量,可以被直接访问

  • 案例:

    /**
    	Java 风格包,包名为 com.abc.demo
    	包对象的源文件名:package.scala
    	com.abc.demo 下的 class 和 object 都能访问包对象的变量和方法
    */
    package object demo {
        val commonVal: String = "家里蹲"
        def commonFunc(): Unit = {
            println(s"他们正在${commonVal}")
        }
    }
    
    /**
    	嵌套风格包,包层级为 com abc demo
    	包对象可与包定义在同一文件中,但是要保证包对象与包声明在同一作用域中
    */
    package com {
        package abc {
            package demo {
                object TestDemo {
                    def main(args: Array[String]): Unit = {
                        println(school)
                    }
                }
            }
            
            // 包对象与包声明要在同一作用域
            package object demo {
                val school: String = "AgriculturalUniversity"
            }
        }
    }
    
    // 包对象定义在与包不同的作用域,包对象变量访问不到
    /*
    package object demo {
        val school: String = "AgriculturalUniversity"
    }
    */
    
    

5. 导包

  • 默认导入的包:

    • import java.lang._
    • import scala._
    • import scala.Predef._
  • 导包语法:

    // 1. 在源文件文件首行导入包,与 Java 一致
    import com.abc.Fruit
    package com.abc.demo
    object Test {
        ...
    }
    
    // 2. 局部导入:在使用时导入,仅在当前作用域可以使用
    package com.abc.demo
    object Test {
        def main(args: Array[String]): Unit = {
            import com.abc.Fruit
            ...
        }
        
        def f1(): Unit = {
            // Fruit 类访问不到
        }
    }
    
    // 3. 通配符导入
    import java.util._
    
    // 4. 给类起名
    import java.util.{ArrayList=>JL}
    
    // 5. 导入相同包的多个类
    import java.util.{HashSet, ArrayList}
    
    // 6. 屏蔽类
    import java.util.{ArrayList =>_,_}
    
    
    // 7. 导入包的绝对路径
    new _root_.java.util.HashMap
    
    
  • 案例说明:

    案例说明
    import com.abc.Fruit引入 com.abc 包下 Fruit(class 和 object)
    import com.abc._引入 com.abc 下的所有成员
    import com.abc.Fruit._引入 Fruit(object) 的所有成员
    import com.abc.{Fruit,Vegetable}引入 com.abc 下的 Fruit 和 Vegetable
    import com.abc.{Fruit=>Shuiguo}引入 com.abc 包下的 Fruit 并更名为 Shuiguo
    import com.abc.{Fruit=>Shuiguo,_}引入 com.abc 包下的所有成员,并将 Fruit 更名为 Shuiguo
    import com.abc.{Fruit=>_,_}引入 com.abc 包下屏蔽 Fruit 类
    new _root_.java.util.HashMap引入的 Java 的绝对路径

二、类和对象

1. 概念

  • 类:对象的抽象或模板
  • 对象:表示具体的事物

2. 语法

object Test {
    def main(args: Array[String]): Unit = {
        val student = new Student()
        // student.name // 报错,私有属性不能访问
        
        println(student.age)
        println(student.gender)
        student.age = 18
        println(student.age)
        
        println(student.getStuId)
        student.setStuId("002")
		println(student.getStuId)
    }
}

/*
	声明类语法:
	[修饰符] class class_name {
		属性
		方法
	}
*/
class Student { // 默认为 public,不能显示的用 public 修饰
    private val name: String = "李雷" // 属性默认为 public
    var age: Int = _ // _ 表示属性默认值,Int 为 0,String 为 null, Boolean 为 false
    var gender: String = _ // _ 只能给 var 型变量赋默认值
    
    @BeanProperty
    var stuId: String = "001" // @BeanProperty 可以自动生成规范的 setter/getter 方法
}

// 一个 scala 源文件可以声明多个类
class teacher {
    ...
}

三、封装

1. 概念

封装是把抽象出的数据和对数据的操作封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作(成员方法),才能对数据进行操作

2. 对比 Java

  • Java 封装:
    • 将属性进行私有化
    • 提供一个公共的 set 方法,用于对属性赋值
    • 提供一个公共的 get 方法,用于获取属性的值
  • Scala 封装:
    • Scala 中的 public 属性,底层实际为 private,并通过 get 方法(obj.field())和 set 方法(obj.field_=(value))对其进行操作,即底层已经实现封装操作
    • 通过 @BeanProperty 注解实现显式的 getter 和 setter 方法可以兼容 Java 框架

3. 访问权限

  • Scala 中属性和方法的默认访问权限为 public,但 Scala 中无 public 关键字
  • private 为私有权限,只在类的内部和伴生对象中可访问
  • protected 为受保护权限,Scala 中受保护权限比 Java 中更严格,同类、子类可以访问,同包无法访问(与 Java 不同)
  • private[包名] 增加包访问权限,包名下的其他类也可以访问
package com.abc.scala.test 

object Person {
    def main(args: Array[String]): Unit = {
        val person = new Person()
        person.say()
        println(person.name)
        println(person.age)
    }
}

class Person {
    private var name: String = "bobo"
    protected var age: Int = 18
    var address: String = "幸福里"
    private[test] var sex: String = "男"
    
    def say(): Unit = {
    	println(s"$name $age $address $sex")
    }
}

class Worker extends Person {
    def test(): Unit = {
        // this.name // error
        this.age 
        this.sex
    }
    
    override def say(): Unit = { // 重写父类方法
        println(s"$age $address $sex")
    }
}

class Animal {
    def test: Unit = {
        // new Person().age // error
    	new Person().sex
    }
}

package com.abc.scala.test2 
class Teacher extends Person {
    def test(): Unit = {
        // this.name // error
        this.age 
        // this.sex // error
    }
}

4. 构造器

和 Java 一样,Scala 构造对象也需要调用构造方法,并且可以有任意多个构造方法

4.1 基本语法
/*
	Scala 类的构造器包括:主构造器和辅助构造器
*/
class class_name(param1: type1,...) {    //  主构造器
    
    def this(param1: type1,...) {   //  辅助构造器
    
    }
    
    def this(param1: type1,...) {   // 辅助构造器可以有多个...
    
    }
}

  • 辅助构造器,函数的名称为 this,可以有多个,编译器通过参数的个数及类型来区分
  • 辅助构造方法不能直接构建对象,必须直接或者间接调用主构造方法
  • 构造器调用其他另外的构造器,要求被调用构造器必须提前声明
4.2 案例
object Student {
    def main(args: Array[String]): Unit = {
        val student = new Student
        student.Student()
        
        val student1 = new Student("张三")
        val student2 = new Student("李四", 20)
    }
}

class Student() { // 无参构造器
    var name: String = _
    var age: Int = _
    
    println("1. 主构造器被调用")
    
    def this(name: String) {
        this()
        this.name = name
        println("2. 辅助构造器一被调用")
        println(s"name:$name age:$age")
    }
    
    def this(name: String, age: Int) {
        this(name)
        this.age = age
        println("3. 辅助构造器二被调用")
        println(s"name:$name age:$age")
    }
    
    def Student(): Unit = {
        println("普通方法被调用")
    }
}

// 构造器私有化
class Teacher private() {
    ...
}

5. 构造器参数

  • 说明:Scala 类的主构造器的形参包括三种类型

    • 未用任何修饰符修饰,此时参数是一个局部变量
    • var 修饰参数,作为类的成员属性使用,可以修改
    • val 修饰参数,作为类只读成员属性使用,不能修改
  • 案例:

    object TestConstructor {
        def main(args: Array[String]): Unit = {
            val student1 = new Student1("tom", 18)
            student1.printInfo()
            
            val student2 = new Student2("jack", 20)
            println(s"name:$student2.name age:$student2.age")
            studen2.name = "curry"
            println(s"name:$student2.name age:$student2.age")
            
            val student3 = new Student3("james", 25)
            // student3.name = "bob" // error
            println(s"name:$student3.name age:$student3.age")
            
            var student4 = new Student4("james", 25)
            println(s"name:$student4.name age:$student4.age school:$student4.school")
            student4 = new Student4("james", 25, "ArtSchool")
            println(s"name:$student4.name age:$student4.age school:$student4.school")
            
        }
    }
    
    // 不使用修饰符
    class Student1(_name: String, _age: Int) {
        // 不推荐使用
        // var name: String = _name
        // var age: Int = _age
        
        def printInfo(): Unit = {
            println(s"name:$name age:$age")
        }
    }
    
    // 使用 var 修饰符,推荐
    class Student2(var name: String, var age: Int) 
    
    // 使用 val 修饰符
    class Student3(val name: String, val age: Int) 
    
    // 使用 var 修饰符且有辅助构造器
    class Student4(var name: String, var age: Int) {
        var school: String = _
        
        def this(name: String, age: Int, school: String) {
            this(name, age)
            this.school = school
        }
    }
    

四、继承和多态

1. 继承

  • 语法:

    class SonClass extends ParentClass { // 1. scala 是单继承
        // 2. 子类继承父类的属性和方法
    }
    
    
  • 案例:

    object TestInherit {
        def main(args: Array[String]): Unit = {
            val stu1 = new Student("张三", 18) // 1-3
            val stu2 = new Student("李四", 20, "1001") // 1-3-4
        }
    }
    
    // 定义父类
    class Person() { // 空参主构造器
        var name: String = _
        var age: Int = _
        
        println("1. 父类的主构造器调用")
        
        def this(name: String, age: Int) {
            this()
            println("2. 父类的辅助构造器调用")
            this.name = name
            this.age = age
        }
        
        def printInfo(): Unit = {
            println(s"Person: $name $age")
        }
    }
    
    // 定义子类
    class Student(name: String, age: Int) extends Person() { // 先调用父类主构造器
        var stdNo: String = _
        
        println("3. 子类的主构造器调用")
        
        def this(name: String, age: Int, stdNo: String) {
            this(name, age)
            println("4. 子类的辅助构造器调用")
            this.stdNo = stdNo
        }
        
        override def printInfo(): Unit = {
            println(s"Student: $name $age $stdNo")
        }
    }
    
    

2. 多态

2.1 动态绑定比较
  • Java

    public class TestDynamicBind {
        public static void main(String[] args) {
            Worker worker = new Worker();
            System.out.println(worker.name);
            worker.hello();
            worker.hi();
            
            System.out.println("================");
            
            Person person = new Worker();
            System.out.println(person.name); // person,静态绑定属性
            person.hello(); // hello worker,动态绑定方法
            // person.hi(); // error
        }
    }
    
    class Person {
        String name = "person";
        
        public void hello() {
            System.out.println("hello person");
        }
    }
    
    class Worker extends Person {
        String name = "worker";
        
        @override
        public void hello() {
            System.out.println("hello worker");
        }
        
        public void hi() {
            System.out.println("hi worker");
        }
    }
    
    
  • Scala

    object TestDynamicBind {
        def main(args: Array[String]): Unit = {
            val person: Person = new Worker
            println(person.name) // worker,动态绑定属性
            person.hello()  // hello worker,动态绑定方法
        }
    }
    
    class Person {
        val name: String = "person"
        
        def hello(): Unit = {
            println("hello person")
        }
    }
    
    class Worker extends Person {
        override val name: String = "worker"
        
        override def hello(): Unit = {
            println("hello worker")
        }
    }
    
2.2 多态案例
object TestMultiStatus {
    def main(args: Array[String]): Unit = {
        def printInfo(person: Person): Unit = {
            person.printInfo()
        }
        
        val person = new Person
        val student = new Student
        val teacher = new Teacher
        
        // 通过动态绑定技术实现同一父类的不同具体实现,调用不同的方法
        printInfo(person) // hello person
        printInfo(student) // hello student
        printInfo(teacher) // hello teacher
    }
}

class Person {
    def printInfo(): Unit = {
        println("hello person")
    }
}

class Student extends Person {
    override def printInfo(): Unit = {
        println("hello student")
    }
}

class Teacher extends Person {
    override def printInfo(): Unit = {
        println("hello teacher")
    }
}

五、抽象类

1. 定义

  • 抽象类:使用 abstract 关键字修饰,相当于模板类,可以包含抽象的属性方法和非抽象的属性方法,可以被继承
  • 抽象属性:没有初始值的属性,只能存在于抽象类中,可以被继承实现
  • 抽象方法:没有具体实现的方法,只能存在于抽象类中,可以被继承实现
object TestAbstractClass {
    def main(args: Array[String]): Unit = {
        val student: Student = new Student
        println(student.name)
        println(student.age)
        println(student.stuNo)
        student.eat()
        student.sleep()
    }
}

// 定义抽象类
abstract class Person {
    // 非抽象属性
    val name: String = "person"
    var age: Int = 19
    
    // 抽象属性
    var stuNo: String
    
    // 非抽象方法
    def eat(): Unit = {
        println("person eat")
    }
    
    // 抽象方法
    def sleep(): Unit
}

// 定义继承类
class Student extends Person { // 继承类也可以定义为抽象类
    override val name: String = "student"
    // override var age: Int = 20 // error,var 属性不能被重写
    age = 20
    
    var stuNo: String = "1001" // 实现抽象属性
    
    override def eat(): Unit = { // 重写方法
        super.eat() // 调用父类的非抽象方法
        println("student eat")
    }
    
    def sleep(): Unit = { // 实现抽象方法,可以不加 override
        println("student sleep")
    }
} 


2. 匿名子类

object TestAnnoymousClass {
    def main(args: Array[String]): Unit = {
        val person: Person = new Person {
            var name: String = "张三"
            def eat(): Unit = println("张三 eat")
        }
        
        println(person.name)
        person.eat()
    }
}

abstract class Person {
    var name: String
    def eat(): Unit
}

六、单例对象

伴生对象

1. 定义

​ Scala 语言是完全面向对象的语言,所以并没有静态的概念和操作。为了能够和 Java 语言交互,就产生了一种特殊的对象来模拟类对象, 该对象为单例对象,也称为类的伴生对象。伴生对象名必须与类名一致,这个类的所有“静态”内容都可以在它的伴生对象中声明

2. 语法案例

// 定义一个类
class Student(val name: String, val age: Int) {
    def printInfo(): Unit = {
        println(s"student: name=$name age=$age school=$Student.school")
    }
}

// 定义类的伴生对象
object Student { // 关键字 object,对象名与类名一致
    // 定义静态的属性
    val school: String = "highSchool"
}

object TestObject {
    def main(args: Array[String]): Unit = {
        val student1 = new Student("tom", 18)
        val student2 = new Student("jerry", 19)
        
        // school 的值是一样的
        student1.printInfo()
        student2.printInfo()
    }
}

3. apply 方法

通过伴生对象的 apply 方法,可以实现不使用 new 方法创建对象

// 定义一个类
class Student private(val name: String, val age: Int) { // 构造方法私有化
    def printInfo(): Unit = {
        println(s"student: name=$name age=$age school=$Student.school")
    }
}

// 定义类的伴生对象
object Student { // 关键字 object,对象名与类名一致
    // 定义静态的属性
    val school: String = "highSchool"
    
    // 定义 apply 方法,创建伴生类的对象实例
    def apply(name: String, age: Int): Student = new Student(name, age)
    
    // apply 方法可以重载
    def apply(): Student = {
        null
    }
}

object TestObject {
    def main(args: Array[String]): Unit = {
        val student1 = Student.apply("tom", 18)
        val student2 = Student("tom", 18) // apply 方法名可以省略
        val student3 = Student()
        
        student1.printInfo()
        student2.printInfo()
    }
}

4. 单例设计模式实现

object TestSingleton {
    def main(args: Array[String]): Unit = {
        val obj1 = Singleton.getInstance()
        val obj2 = Singleton.getInstance()
        
        println(obj1)
        println(obj2)
        
    }
}

class Singleton private(name: String, age: Int) {
    
}

object Singleton {
    // 饿汉式
    // private val obj: Singleton = new Singleton("孙悟空", 500)
    // def getInstance(): Singleton = obj
    
    // 懒汉式
    private var obj: Singleton = _
    def getInstance(): Singleton = if(obj == null) new Singleton("孙悟空", 500) else obj
}

七、特质

1. 定义

  • Scala 语言中,采用特质 (trait) 来代替接口的概念,当多个类具有相同的特质(特征)时,就可以将这个特质独立出来,采用关键字 trait 声明
  • Scala 中的 trait 中既可以有抽象属性和方法,也可以有具体的属性和方法,一个类可以混入(mixin)多个特质
  • Scala 引入 trait 特征,第一可以替代 Java 的接口,第二个也是对单继承机制的一种补充;同时所有的 Java 接口都可以当做 Scala 特质使用

2. 基本语法

/** 特质声明语法:
    trait traitName {

    }
*/
trait PersonTrait {
    // 定义抽象和非抽象属性
    val name: String = "tom"
    var age: Int
    
    // 定义抽象和非抽象方法
    def say(): Unit = {
        println("person can say")
    }
    
    def eat(): Unit
    
}

3. 特质混入

  • 语法:

    /** 
    	使用 extends 和 with 关键字为类混入特质
    */
    
    // 存在父类
    class SonClass extends ParentClass with trait1 with trait2 {}
    
    // 没有父类
    class SubClass extends trait1 with trait2 with trait3 {}
    
    
    
  • 案例:

    object TestMixIn {
        def main(args: Array[String]): Unit = {
            val student1 = new Student
            student1.eat()
            student1.study()
            student1.increase()
            student1.play()
            student1.increase()
            student1.dating()
            student1.increase()
            
            println("===================")
            
            // 动态混入
            val studentWithTalent = new Student with Talent {
                override def singing(): Unit = println("student is good at singing")
        		override def dancing(): Unit = println("student is good at dancing")
            }
            studentWithTalent.eat()
            studentWithTalent.study()
            studentWithTalent.increase()
            studentWithTalent.play()
            studentWithTalent.increase()
            studentWithTalent.dating()
            studentWithTalent.increase()
            studentWithTalent.singing()
            studentWithTalent.dancing()
        }
    }
    
    class Person {
        val name: String = "person"
        val age: Int = 1
        
        def eat(): Unit = println(s"person $name is eating")
    }
    
    trait Young {
        val name: String = "young"
        var age: Int
        
        def play(): Unit = println("young person $name is playing")
        def dating(): Unit
    }
    
    trait Kownledge {
        var amount: Int = 0
        
        def increase(): Unit
    }
    
    trait Talent {
        def singing(): Unit
        def dancing(): Unit
    }
    
    class Student extends Person with Young with Kownledge {
        // 存在多个同名的非抽象属性,必须重写
        override val name: String = "student"
        
        // 实现抽象方法
        def dating(): Unit = println(s"student $name is dating")
        def increase(): Unit = {
            amount += 1
            println(s"$name kownledge is increasing")
        }
        
        // 定义自有方法
        def study(): Unit = println(s"student $name is studying")
        
        // 重写父类方法
        override def eat(): Unit = println(s"student $name is eating")
    }
    

4. 特质叠加

4.1 问题引出

​ 由于一个类可以继承 (extends) 父类和混入 (mixin) 多个 trait,当继承的父类和混入的特质中具有相同的属性和相同的方法 (方法名/参数列表/返回值均相同) 时,必然会出现继承冲突问题

​ 继承冲突分为两种情况:第一种是混入的多个 trait 中具有相同的具体方法,且 trait 之间没有任何关系;混入的多个 trait 中具有相同的具体方法,且 trait 都继承自相同的父 trait,即钻石冲突问题

4.2 解决方法
  • 第一种冲突:

    object TestOverly {
        def main(args: Array[String]): Unit = {
            val student = new Student
            println(student.name)
            student.hello() // talent hello - student hello
        }
    }
    
    class Person {
        val name: String = "person"
        
        def hello(): Unit = {
            println("person hello")
        }
    }
    
    trait Kownledge {
        val name: String = "kownledge"
        def hello(): Unit = {
            println("kownledge hello")
        }
    }
    
    trait Talent {
        val name: String = "talent"
        def hello(): Unit = {
            println("talent hello")
        }
    }
    
    class Student extends Person with Kownledge with Talent {
        // 冲突属性必须重写
        override val name: String = "student"
        
        // 冲突方法必须重写
        override def hello(): Unit = {
            super.hello() // 调用的是最后一个混入特质的该方法
            println("student hello")
        }
    }
    
    
  • 第二种冲突:

    object TestOverly {
        def main(args: Array[String]): Unit = {
            val myBall = new MyBall
            println(myBall.describe()) // my ball is a red-foot-ball
        }
    }
    
    trait Ball {
        def describe(): String = {
            "ball"
        }
    }
    
    trait ColorBall {
        val color: String = "red"
        def describe(): String = {
            color + "-" + super.describe()
        }
    }
    
    trait CategoryBall {
        val category: String = "foot"
        def describe(): String = {
            category + "-" + super.describe()
        }
    }
    
    class MyBall extends CategoryBall with ColorBall {
        // 冲突方法必须重写
        override def describe(): String = {
            // super调用采用特质叠加的策略
            // 先调用最后一个混入特质的方法再从右往左调用与其同父特质的特质的方法最后调用父特质的方法
            "my ball is a " + super.describe() 
            
            // 如果想要调用某个指定的混入特质中的方法,可以增加约束:super[traitName]
    		// "my ball is a " + super[CategoryBall].describe() 
        }
    }
    

5. 特质自身类型

5.1 概念
  • 特质自身类型是在特质或类中定义一个外部的类或特质的持有,相当于 Java Spring 中的依赖注入

  • 语法:

    trait traitName {
        /*
        	_ 表示自身类型别名的通配
        	type 是持有的具体类名或特质名
        */
        _: type =>
    }
    
5.2 案例

模拟用户注册

object TestSelfType {
    def main(args: Array[String]): Unit = {
        val regUser = new RegUser("bob", "123456")
        regUser.insertUser()
    }
}

// 定义用户类
class User(var name: String, var password: String)

// 定义用户操作特质
trait UserDao {
    // 使用特质自身类型将 User 类引入,类似于 spring 的依赖注入
    /*  @Autowired
    	private User user;
    */
    _: User =>
    
    // 插入用户信息到数据库
    def insertUser(): Unit = { // 方法通过自身类型 this 可以获取 User 信息
        println(s"insert into user:${this.name} into db")
    }
}

// 定义注册用户类,继承用户类并混入用户操作特质
class RegUser(name: String, password: String) extends User(name, password) with UserDao

6 特质VS抽象类

  • 优先使用特质,一个类扩展多个特质是很方便的,但却只能扩展一个抽象类
  • 如果需要构造函数参数,则使用抽象类。因为抽象类可以定义带参数的构造函数,而特质不行 (有无参构造器)

八、扩展

1. 类型检查和转换

class Person

class Student extends Person

object TestExtends {
    def main(args: Array[String]): Unit = {
        val person: Person = new Person
        val person2: Person = new Student
        val student: Student = new Student
        
        //(1)判断对象是否为某个类型的实例:isInstanceOf[className]
        val res1: Boolean = person.isInstanceOf[Person] // true
        val res2: Boolean = person.isInstanceOf[Student] // false
        val res3: Boolean = person2.isInstanceOf[Student] // true
        val res4: Boolean = student.isInstanceOf[Person] // true
        
        //(2)将对象转换为某个类型的实例:asInstanceOf[className]
        if (res3) { // 首先对象必须为该类型实例才能转换
            val student2: Student = person2.asInstanceOf[Student]
            println(student2)
        }
        
        //(3)获取类的信息:classOf[className]
        val pClass: Class[Person] = classOf[Person]
        println(pClass)
        
    }
}

2. 枚举类和应用类

/*
	枚举类定义语法:
	object objName extends Enumeration {
		val fieldName = Value(i: Int, value: String)
	}
*/
object WorkDay extends Enumeration {
    val MONDAY = Value(1, "星期一") // 枚举类属性一般全大写
    val TUESDAY = Value(2, "星期二")
}

/*
	应用类定义语法:
	object objName extends App {
		// 可执行的语句
	}
*/
object MyApp extends App { // 必须定义为 object
    // 省略了 main 方法,内部有 main 方法的封装
    println(WorkDay.MONDAY)
} 

3. Type 定义新类型

// 使用 type 关键字可以定义新的数据数据类型名称,本质上就是类型的一个别名
object Test {
    def main(args: Array[String]): Unit = {
        
        type MyString = String
        
        var str: MyString = "abc"
        
        def test(): MyString = "xyz"
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值