Scala面向对象编程(高级部分)

这篇具有很好参考价值的文章主要介绍了Scala面向对象编程(高级部分)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 静态属性和静态方法

(1)回顾Java中的静态概念

public static 返回值类型 方法名(参数列表) {方法体} 静态属性… 说明:
Java中静态方法并不是通过对象调用的,而是通过类对象调用的,所以静态操作并不是面向对象的。

(2)Scala中静态的概念-伴生对象

①Scala语言是完全面向对象(万物皆对象)的语言,所以并没有静态的操作(即在Scala中没有静态的概念)。也没有static关键字, 但是为了能够和Java语言交互(因为Java中有静态概念),就产生了一种特殊的对象来模拟类对象,我们称之为类的伴生对象。这个类的所有静态内容都可以放置在它的伴生对象中声明和调用
  ②伴生对象的小结

1. Scala中伴生对象采用object关键字声明,伴生对象中声明的全是 "静态"内容,
    可以通过伴生对象名称直接调用。
2. 伴生对象对应的类称之为伴生类,伴生对象的名称应该和伴生类名一致。
3. 伴生对象中的属性和方法都可以通过伴生对象名直接调用访问    
4. 从语法角度来讲,所谓的伴生对象其实就是类的静态方法和静态变量的集合
5. 从技术角度来讲,scala还是没有生成静态的内容,只不过是将伴生对象生成了一个新的类,
    实现属性和方法的调用。
6. 从底层原理看,伴生对象实现静态特性是依赖于 public static final MODULE$ 实现的。
7. 伴生对象的声明应该和伴生类的声明在同一个源码文件中(如果不在同一个文件中会运行错误!),
    但是如果没有伴生类,也就没有所谓的伴生对象了,所以放在哪里就无所谓了。
8. 如果 class A 独立存在,那么A就是一个类, 如果 object A 独立存在,那么A就是一个"
静态"性质的对象[即类对象], 在 object A中声明的属性和方法可以通过 A.属性 和 A.方法
来实现调用

(3)伴生对象apply方法

在伴生对象中定义apply方法,可以实现: 类名(参数) 方式来创建对象实例.

class Child private (var name: String, var age: Int, var address: String) {
Child.nums += 1
}
object Child {
var nums: Int = _
// apply方法会通过类(实参列表)调用到
def apply(name: String, age: Int, address: String): Child = {
println("apply()...")
new Child(name, age, address)
}
}

object Test {
def main(args: Array[String]): Unit = {
//加入apply方法后可以将主构造器加上private修饰,这样就
//只能通过apply方法调用来生成对象了
//val child1 = new Child("小花1", 10, "昌平")
//println(child1.name)
val array1 = new Array[Int](8)
val array2 = Array(1, 3, 8, 7)

val child2 = Child("小明", 5, "朝阳")// 自动调用apply方法
println(child2.name)
}
}

2. 单例模式

定义:保证在整个的软件系统中,某个类只能存在一个对象实例。
应用场景:

比如Hibernate的SessionFactory,它充当数据存储源的代理,并负责创建Session对象。SessionFactory并不是轻量级的,一般情况下,一个项目通常只需要一个SessionFactory就够,这是就会使用到单例模式。
Akka [ActorySystem 单例] AKKA

Scala中没有静态的概念,所以为了实现Java中单例模式的功能,可以直接采用类对象(即伴生对象)方式构建单例对象

方式一:懒汉式

object TestSingleTon extends App{
val singleTon = SingleTon.getInstance
val singleTon2 = SingleTon.getInstance
println(singleTon.hashCode() + " " + singleTon2.hashCode())
}
//将SingleTon的构造方法私有化
class SingleTon private() {}

object SingleTon {
private var s:SingleTon = null
def getInstance = {
if(s == null) {
s = new SingleTon
}
s
}
}
object TestSingleTon extends App {
val singleTon = SingleTon.getInstance
val singleTon2 = SingleTon.getInstance
println(singleTon.hashCode() + " ~ " + singleTon2.hashCode())
println(singleTon == singleTon2)
}
//将SingleTon的构造方法私有化
class SingleTon private() {
println("~~~")
}
object SingleTon {
private val s: SingleTon = new SingleTon
def getInstance = {
s
}
}
//说明:饿汉式

3.接口

(1)回顾Java接口

声明接口
   interface 接口名
实现接口
   class 类名 implements 接口名1,接口2
(1)在Java, 一个类可以实现多个接口。
(2)在Java中,接口之间支持多继承
(3)接口中属性都是常量
(4)接口中的方法都是抽象的

(2)Scala接口的介绍

从面向对象来看,接口并不属于面向对象的范畴,Scala是纯面向对象的语言,在Scala中,没有接口, 也没有implements关键字。Scala语言中,采用trait(特质,特征)来代替接口的概念,也就是说,多个类具有相同的特征(特征)时,就可以将这个特质(特征)独立出来,采用关键字trait声明。

(3)特质

trait 的声明
    trait 特质名 {
       trait体
     }**

trait 命名 一般首字母大写. Cloneable , Serializable
object T1 extends object T1 extends Serializable { } ,其中 Serializable 就是scala的一个特质。
在scala中,java中的接口可以当做特质使用

一个类具有某种特质(特征),就意味着这个类满足了这个特质(特征)的所有要素,所以在使用时,也采用了extends关键字,如果有多个特质或存在父类,那么需要采用with关键字连接

没有父类:
    class 类名 extends 特质1 with 特质2 with 特质3 ..
有父类 :
   class 类名 extends 父类 with 特质1 with 特质2 with 特质3

(4)特质的再说明

Scala提供了特质(trait),特质可以同时拥有抽象方法和具体方法,一个类可以实现/继承多个特质。
特质中没有实现的方法就是抽象方法。类通过extends继承特质,通过with可以继承多个特质
所有的java接口都可以当做Scala特质使用

abstract class Pet(var name:String, var age: Int, var weight: Double) {
var id: Int // 抽象的属性
// 普通方法
// 抽象方法, 没有=和方法体
def eat
override def toString(): String = {
name + "," + age + "," + weight
}
}
class Dog extends Pet("小黄", 2, 2.5) {
    // Pet(实参列表)作用是调用父类构造器,完成属性的初始化
var id = 20
override def eat = println("吃狗粮")
     // 如果是方法的实现, 可以省略override
def kanjia(): Unit = {
println("看家狗")
}
}
class Bird(name:String, age: Int, weight: Double)
                        extends Pet(name, age, weight) {
var id = 30
def eat = println("吃虫子")
}

object PetTest {
def main(args: Array[String]): Unit = {
//new Pet("小黑", 2, 20)
val dog = new Dog
val bird = new Bird("小飞", 1, 0.2)
println(dog)
println(bird)

var v : Pet = new Dog() // 多态
v = bird
//((Dog)v).kanjia
if (v.isInstanceOf[Dog]) {
v.asInstanceOf[Dog].kanjia // 造型
}
}
}

(5)带有特质的对象:动态混入
1.除了可以在类声明时继承特质以外,还可以在构建对象时混入特质,扩展对象的功能
2.此种方式也可以应用于对抽象类功能进行扩展
3.动态混入是Scala特有的方式(java没有动态混入),可在不修改类声明/定义的情况下,扩展类的功能,非常的灵活,耦合性低 。
4.动态混入可以在不影响原有的继承关系的基础上,给指定的类扩展功能。

//写一个特质Flyer, 写两个抽象方法takeOff, fly, 具体方法land
trait Flyer {
var name:String // 这是抽象属性, 在特质中变成抽象方法
var speed: Int = 2000 // 普通属性, 在特质中变成抽象方法

def takeOff():Unit
def fly
def land = println("我要着陆了....")
}
//写一个子类Plane, 再混入其他特质 with后面只允许特质, extends后面可以是特质也可以是类
//在类中使用with是静态混入, 只要创建本类对象,都具备这些特质
class Plane extends Flyer with Serializable with Comparable[Plane] {
var name = "大飞机" // 覆盖属性
// 在子类中重新定义
// 特质中的普通属性, 在子类中也仍然需要重新定义, 提供了set方法, 会被特质的特殊类调用.
def takeOff(): Unit = println("飞机起飞中, 推背感强")
override def fly: Unit = println("平稳飞行中...")
override def compareTo(o: Plane) = 0
}

class Man {
type T
}

class Chinese extends Man {
override type T = String
}
class English extends Man {
override type T = Double
}

object TraitExer {

def main(args: Array[String]): Unit = {
type P = Plane
var p: P = new P
println(p)
p.fly
}

def main3(args: Array[String]): Unit = {
val man1 = new Man
// 在创建对象时使用with特质, 也可以实现混入,称为动态混入, 混入的特质只对当前对象有效
val man2 = new Man with Flyer with Serializable {
var name = "abc"
override def takeOff(): Unit = println("不知怎么就会飞了")
override def fly: Unit = println("引力对我没用")
}
man2.fly

val man3 = new Man{} // 匿名内部类

}

def main2(args: Array[String]): Unit = {
val plane = new Plane
plane.takeOff()
plane.land

val flyer2 = new Flyer {
var name = "yyy"
override def takeOff(): Unit = println("lll")
override def fly: Unit = println("fly")
}

}
}

(6)叠加特质
构建对象的同时如果混入多个特质,称之为叠加特质,那么特质声明顺序从左到右,方法执行顺序从右到左。

trait Operate4 {
println("Operate4...")
def insert(id : Int)
}
trait Data4 extends Operate4 {
println("Data4")
override def insert(id : Int): Unit = {
println("插入数据 = " + id)
}
}
trait DB4 extends Data4 {
println("DB4")
override def insert(id : Int): Unit = {
print("向数据库")
super.insert(id)
}
}
trait File4 extends Data4 {
println("File4")
override def insert(id : Int): Unit = {
print("向文件")
super.insert(id)
}}
class MySQL4 {}
// 1.Scala在叠加特质的时候,会首先从后面的特质开始执行
// 2.Scala中特质中如果调用super,并不是表示调用父特质的方法,而是向前面(左边)继续查找特质,如果找不到,才会去父特质查找
val mysql = new MySQL4 with DB4 with File4
//val mysql = new MySQL4 with File4 with DB4
mysql.insert(888)

上述程序执行结果为:

Operate4...
Data4
DB4
File4
向文件向数据库插入数据 = 888

debug整个过程发现,最后一行程序执行时先到了trait File4中的insert方法,然后又去了DB4的insert方法,最后去了Data4的insert方法,执行打印语句完毕后按逆顺序出栈

叠加特质
叠加特质注意事项和细节
1.特质声明顺序从左到右。
2.Scala在执行叠加对象的方法时,会首先从后面的特质(从右向左)开始执行
3.Scala中特质中如果调用super,并不是表示调用父特质的方法,而是向前面(左边)继续查找特质,如果找不到,才会去父特质查找
4.如果想要调用具体特质的方法,可以指定:super[特质].xxx().其中的泛型必须是该特质的直接超类类型

将上述程序中Trait File 改为以下内容:

trait File4 extends Data4 {
println("File4")
override def insert(id : Int): Unit = {
print("向文件")
super[Data4].insert(id)
}
}

此时执行结果为:

Operate4...
Data4
DB4
File4
向文件插入数据 = 888

(7)在特质中重写抽象方法
方式1 : 去掉 super()…
方式2: 调用父特质的抽象方法,那么在实际使用时,没有方法的具体实现,无法编译通过,为了避免这种情况的发生。可重写抽象方法,这样在使用时,就必须考虑动态混入的顺序问题。

理解 abstract override 的小技巧分享:可以这里理解,当我们给某个方法增加了abstract override
后,就是明确的告诉编译器,该方法确实是重写了父特质的抽象方法,但是重写后,该方法仍然是一个抽象方法(因为没有完全的实现,需要其它特质继续实现[通过混入顺序])

trait Operate5 {
def insert(id : Int)
}
trait File5 extends Operate5 {
abstract override def insert( id : Int ): Unit = {
println("将数据保存到文件中..")
super.insert(id)
}
}

trait DB5 extends Operate5 {
def insert( id : Int ): Unit = {
println("将数据保存到数据库中..")
}
}
class MySQL5 {}
val mysql5 = new MySQL5 with DB5 with File5

重写抽象方法时需要考虑混入特质的顺序问题和完整性问题 看4个案例,并判断结果。
var mysql2 = new MySQL5 with DB5 // ok
mysql2.insert(100)
var mysql3 = new MySQL5 with File5 // error
mysql2.insert(100)
var mysql4 = new MySQL5 with File5 with DB5// error
mysql4.insert(100)
var mysql4 = new MySQL5 with DB5 with File5// ok
mysql4.insert(100)

富接口概念:即该特质中既有抽象方法,又有非抽象方法

trait Operate {
def insert( id : Int ) //抽象
def pageQuery(pageno:Int, pagesize:Int): Unit = { //实现
println("分页查询")
}
}

特质中的具体字段

特质中可以定义具体字段,如果初始化了就是具体字段,如果不初始化就是抽象字段。混入该特质的类就具有了该字段,字段不是继承,而是直接加入类,成为自己的字段。

特质中的抽象字段

特质中未被初始化的字段在具体的子类中必须被重写。

特质构造顺序

特质也是有构造器的,构造器中的内容由“字段的初始化”和一些其他语句构成。具体实现请参考“特质叠加”

第一种特质构造顺序(声明类的同时混入特质)
调用当前类的超类构造器
第一个特质的父特质构造器
第一个特质构造器
第二个特质构造器的父特质构造器, 如果已经执行过,就不再执行
第二个特质构造器
…重复4,5的步骤(如果有第3个,第4个特质)
当前类构造器
第2种特质构造顺序(在构建对象时,动态混入特质)
调用当前类的超类构造器
当前类构造器
第一个特质构造器的父特质构造器
第一个特质构造器.
第二个特质构造器的父特质构造器, 如果已经执行过,就不再执行
第二个特质构造器
…重复5,6的步骤(如果有第3个,第4个特质)
当前类构造器
分析两种方式对构造顺序的影响
第1种方式实际是构建类对象, 在混入特质时,该对象还没有创建。
第2种方式实际是构造匿名子类,可以理解成在混入特质时,对象已经创建了。

扩展类的特质

特质可以继承类,以用来拓展该类的一些功能(和java的不同)

trait LoggedException extends Exception{
def log(): Unit ={
println(getMessage()) // 方法来自于Exception类
}
}

所有混入该特质的类,会自动成为那个特质所继承的超类的子类

trait LoggedException extends Exception{
def log(): Unit ={
println(getMessage()) // 方法来自于Exception类
}
}
//UnhappyException 就是Exception的子类.
class UnhappyException extends LoggedException{
// 已经是Exception的子类了,所以可以重写方法
override def getMessage = "错误消息!"
}

如果混入该特质的类,已经继承了另一个类(A类),则要求A类是特质超类的子类,否则就会出现了多继承现象,发生错误。
Scala面向对象编程(高级部分),scala,开发语言,后端

自身类型

自身类型(self-type):主要是为了解决特质的循环依赖问题,同时可以确保特质在不扩展某个类的情况下,依然可以做到限制混入该特质的类的类型。
应用案例举例说明自身类型特质,以及如何使用自身类型特质

//Logger就是自身类型特质
trait Logger {
// 明确告诉编译器,我就是Exception,如果没有这句话,下面的getMessage不能调用
this: Exception =>
def log(): Unit ={
// 既然我就是Exception, 那么就可以调用其中的方法
println(getMessage)
}
}

4. type关键字

使用type关键字可以定义新的数据类型名称
本质上就是类型的一个别名

type S = String
var v : S = “abc”
def test() : S = “xyz”

5. 嵌套类

在Scala中,你几乎可以在任何语法结构中内嵌任何语法结构。如在类中可以再定义一个类,这样的类是嵌套类,其他语法结构也是一样。
嵌套类类似于Java中的内部类。

public class TestJavaClass {
public static void main(String[] args) {
//创建一个外部类对象
OuterClass outer1 = new OuterClass();
//创建一个外部类对象
OuterClass outer2 = new OuterClass();
// 创建Java成员内部类
// 说明在Java中,将成员内部类当做一个属性,因此使用下面的方式来创建 outer1.new InnerClass().
OuterClass.InnerClass inner1 = outer1.new InnerClass();
OuterClass.InnerClass inner2 = outer2.new InnerClass();

//下面的方法调用说明在java中,内部类只和类型相关,也就是说,只要是
//OuterClass.InnerClass 类型的对象就可以传给 形参 InnerClass ic
inner1.test(inner2);
inner2.test(inner1);

// 创建Java静态内部类
// 因为在java中静态内部类是和类相关的,使用 new OuterClass.StaticInnerClass()
OuterClass.StaticInnerClass staticInner = new OuterClass.StaticInnerClass();
}}
class OuterClass { //外部类
class InnerClass { //成员内部类
public void test( InnerClass ic ) {
System.out.println(ic);
}}

static class StaticInnerClass { //静态内部类
}}

scala嵌套类的使用1:

class ScalaOuterClass {
class ScalaInnerClass { //成员内部类
}
}
object ScalaOuterClass { //伴生对象
class ScalaStaticInnerClass { //静态内部类
}
}
val outer1 : ScalaOuterClass = new ScalaOuterClass();
val outer2 : ScalaOuterClass = new ScalaOuterClass();

// Scala创建内部类的方式和Java不一样,将new关键字放置在前,使用 对象.内部类 的方式创建
val inner1 = new outer1.ScalaInnerClass()
val inner2 = new outer2.ScalaInnerClass()
//创建静态内部类对象
val staticInner = new ScalaOuterClass.ScalaStaticInnerClass()
println(staticInner)

scala嵌套类的使用2:

请编写程序,在内部类中访问外部类的属性和方法两种方法。
方式一:

class ScalaOuterClass {
var name : String = "scott"
private var sal : Double = 1.2
class ScalaInnerClass { //成员内部类
def info() = {
// 访问方式:外部类名.this.属性名
// 怎么理解 ScalaOuterClass.this 就相当于是 ScalaOuterClass
        这个外部类的一个实例,
// 然后通过 ScalaOuterClass.this 实例对象去访问 name 属性
// 只是这种写法比较特别,学习java的同学可能更容易理解
         ScalaOuterClass.class 的写法.
println("name = " + ScalaOuterClass.this.name
+ " age =" + ScalaOuterClass.this.sal)
}
}
}
object ScalaOuterClass { //伴生对象
class ScalaStaticInnerClass { //静态内部类
}
}
//调用成员内部类的方法
inner1.info()

方式二:
内部类如果想要访问外部类的属性,也可以通过外部类别名访问(推荐)。即:访问方式:外部类名别名.属性名 【外部类名.this 等价 外部类名别名】

class ScalaOuterClass {
myOuter => //这样写,你可以理解成这样写,myOuter就是代表外部类的一个对象.
class ScalaInnerClass { //成员内部类
def info() = {
println("name = " + ScalaOuterClass.this.name
+ " age =" + ScalaOuterClass.this.sal)
println("-----------------------------------")
println("name = " + myOuter.name
+ " age =" + myOuter.sal)
}}
// 当给外部指定别名时,需要将外部类的属性放到别名后.
var name : String = "scott"
private var sal : Double = 1.2
}

object ScalaOuterClass { //伴生对象
class ScalaStaticInnerClass { //静态内部类
}
}
inner1.info()类型投影
先看一段代码,引出类型投影


class ScalaOuterClass3 {
myOuter =>
class ScalaInnerClass3 { //成员内部类
def test(ic: ScalaInnerClass3): Unit = {
System.out.println(ic)
}
}
}

分析以下代码正确/错误:

object Scala01_Class {
    def main(args: Array[String]): Unit = {
        val outer1 : ScalaOuterClass3 = new ScalaOuterClass3();
        val outer2 : ScalaOuterClass3 = new ScalaOuterClass3();
        val inner1 = new outer1.ScalaInnerClass3()
        val inner2 = new outer2.ScalaInnerClass3()
        inner1.test(inner1) // ok
        inner1.test(inner2) // error 原因是scala内部类对象和外部类对象相关.
        //这时可以使用类型投影来屏蔽类型不同
}
}

解决方式-使用类型投影
类型投影是指:在方法声明上,如果使用 外部类#内部类 的方式,表示忽略内部类的对象关系,等同于Java中内部类的语法操作,我们将这种方式称之为 类型投影(即:忽略对象的创建方式,只考虑类型)文章来源地址https://www.toymoban.com/news/detail-707255.html

到了这里,关于Scala面向对象编程(高级部分)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Scala(第六章 面向对象)

    1、 Scala的面向对象思想和Java的面向对象思想和概念是一致的。 2、Scala中语法和Java不同,补充了更多的功能。 1)基本语法 1 2)Scala包的三大作用(和Java一样) 1、区分相同名字的类 2、当类很多时,可以很好的管理类 3、控制访问范围 6.1.1 包的命名 1)命名规则 只能包含数

    2024年02月13日
    浏览(45)
  • Scala之面向对象

    目录 Scala包: 基础语法: Scala包的三大作用: 包名的命名规范: 写包的好处: 包对象: 导包说明: 类和对象: 定义类: 封装: 构造器:  主从构造器的加载机制: 继承: 基础语法: 抽象属性: 多态: Java中的多态测试 Scala测试如下: Scala的面向对象思想和Java是一致的

    2023年04月15日
    浏览(29)
  • 06-Scala面向对象

    ​ Scala是一门完全面向对象的语言,摒弃了Java中很多不是面向对象的语法。 ​ 虽然如此,但其面向对象思想和 Java的面向对象思想还是一致的 1)基本语法 Scala中基本的package包语法和 Java 完全一致 例如: 2)Scala包的三大作用(和Java一样) 区分相同名字的类 当类很多时,可

    2024年02月07日
    浏览(35)
  • 【Scala】——面向对象

      Scala 有两种包的管理风格。 第一种 Java 的包管理风格相同,每个源文件一个包(包 名和源文件所在路径不要求必须一致),包名用“.”进行分隔以表示包的层级关系,如 com.atguigu.scala。 另一种风格,通过嵌套的风格表示层级关系,一个源文件中可以声明多个 package,子

    2024年01月25日
    浏览(41)
  • Scala面向对象

    组成结构 •构造函数: 在创建对象的时候给属性赋值 •成员变量: •成员方法(函数) •局部变量 •代码块 每个类都有一个主构造器,这个构造器和类定义\\\"交织\\\"在一起类名后面的内容就是主构造器,如果参数列表为空的话,()可以省略 scala的类有且仅有一个主构造器,要想提

    2024年02月09日
    浏览(32)
  • Scala函数式编程【从基础到高级】

    目录 函数基础 基本语法 函数参数 函数至简原则 至简原则细节  函数高级 高阶函数 函数的3种高阶用法: 1、函数作为值传递 2、函数作为参数传递 匿名函数作参数传递 3、函数作为返回值传递 匿名函数的至简规则 高阶函数的应用  案例-将数组中的元素全部+1后返回  匿名

    2024年02月11日
    浏览(43)
  • 2023_Spark_实验九:Scala函数式编程部分演示

    需求: 1、做某个文件的词频统计//某个单词在这个文件出现次数 步骤: 1、文件单词规律(空格分开) 2、单词切分 3、单词的统计 (k,v)-(k:单词,V:数量) 4、打印 框架: 1、单例对象,main() 2、创建CONF 3、创建SC--读取文件的方式--》RDD 4、RDD进行处理 5、关闭资源 一、新

    2024年02月08日
    浏览(43)
  • 2023_Spark_实验七:Scala函数式编程部分演示

    1、Scala中的函数 在Scala中,函数是“头等公民”,就和数字一样。可以在变量中存放函数,即:将函数作为变量的值(值函数)。 2、匿名函数 3、带函数参数的函数,即:高阶函数 示例1: (*)首先,定义一个最普通的函数 (*)再定义一个高阶函数 (*)分析这个高阶函数

    2024年02月08日
    浏览(58)
  • 你知道Scala编程语言吗?Scala基础教程【建议收藏】

    作者:i阿极 作者简介:Python领域新星作者、多项比赛获奖者:博主个人首页 😊😊😊如果觉得文章不错或能帮助到你学习,可以点赞👍收藏📁评论📒+关注哦!👍👍👍 📜📜📜如果有小伙伴需要数据集和学习交流,文章下方有交流学习区!一起学习进步!💪 Scala是一种

    2023年04月08日
    浏览(80)
  • 大数据开发语言Scala(一)——scala入门

    累了,基础配置不想写了,直接抄了→Scala的环境搭建 这里需要注意的是,创建新项目时,不要用默认的Class类,用Object,原因看→scala中的object为什么可以直接运行 package : 包,等同于java中的package object :,声明一个单例对象(伴生对象) main方法 :从外部可以直接

    2024年02月05日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包