Scala单例对象

不属于单个实例的方法和值属于单例对象,用关键字object而不用class来标记。

package test

object Blah {
  def sum(l: List[Int]): Int = l.sum
}

这个sum方法是全局可用的,并且可以用test.Blah.sum来引用或引入。

单例对象某种程度来说是定义一个单一使用类,不能直接实例化,并且在object定义处有一个同名的val成员。实际上,像val,单例对象可以被定义为一个特征或类的成员,虽然这不是典型用法。

单例对象可以扩展类和特征。实际上,不带type parametersCase类会默认创建一个同名的单例对象,实现了特征[Function*]。

伴生

大部分单例对象不是独立的,而是和相同名字的类关联。前面提到的Case类的同名单例对象,就是一个例子。这种情况下,单例对象被称为类的伴生对象(companion object),类称为对象的伴生类(companion class)

Scaladoc对类和其伴生对象之间跳转做了特殊支持:可以点击大的”C”或者”O”圆圈图标跳转到伴生对象。

class IntPair(val x: Int, val y: Int)

object IntPair {
  import math.Ordering
  implicit def ipord: Ordering[IntPair] =
    Ordering.by(ip => (ip.x, ip.y))
}

看到typeclass示例作为implicit values是很常见的,如上面的在伴生中定义的ipord。这是因为伴生成员包含在相关值的默认隐式搜索中。

给Java程序员提示

Scala中static不是一个关键字。相反,所有成员都是静态的,包括类,都应该归为单例对象。它们可以用相同的语法引用,单独或者作为一个整体被引入等等。

Java程序员会频繁定义静态成员,也许是private的,作为实例成员的辅助实现。这些都转为使用伴生对象,一种常用模式是在类中引入伴生对象的成员。如下:

class X {
  import X._

  def blah = foo
}

object X {
  private def foo = 42
}

这种使用方式展现了另外一个特性:在private上下文中,类和它的伴生对象是友元。object X可以访问class X的私有成员,反之亦然。想要有真正的私有成员,使用private[this]

为了给Java提供方便,在单例对象中直接定义的方法(包括varval)也会在伴生类中定义静态方法,叫做static forwarder。对于object X,其它成员可以用X$.MODULE$静态字段访问。如果你把所有实现都放在伴生对象中并且发现就剩下一个不用实例化的类了,那就把类删掉。static forwarder仍然会被创建。

以下是整合了单例对象讲解的完整博客内容: # Scala实现手机号码类型识别:从C语言基础到实战 作为学过C语言的零基础学习者,我们来看看Scala中如何实现手机号码类型识别。本文会结合C语言基础,对比介绍Scala的数组、函数与单例对象语法,再完成功能实现。 ## 一、Scala数组基础(对比C语言) 在C语言中,数组是固定长度、同类型元素的集合,比如 `int arr[5];`。而Scala的数组: - **不可变特性**:默认创建后元素不可变(修改需重新赋值)。 - **定义方式**:通过 `Array` 类创建。 示例: ```scala // C语言数组定义 // int cArray[3] = {1, 2, 3}; // Scala数组定义 val scalaArray = Array(1, 2, 3) // 自动推断类型为Array[Int] ``` ## 二、Scala函数定义语法(对比C语言) C语言中,函数定义会声明返回值类型,如 `void func() { ... }` 表示无返回值。Scala函数语法更明确: - **`def` 关键字**:Scala用 `def` 定义函数。 - **返回类型声明**:Scala强制显式声明返回类型(少数递归场景除外)。无有意义返回值时,用 `Unit`(类似C语言的 `void`)。 - **函数定义结构**: ```scala def 函数名(参数: 参数类型): 返回类型 = { // 函数体 } ``` 例如: ```scala def identify(segment: String): Unit = { // 函数体逻辑,无实际返回值,用Unit } ``` ## 三、Scala单例对象(对比C语言全局函数) 在C语言中,全局函数可直接调用(如 `printf`)。Scala通过 **单例对象** 实现类似功能,但更强调封装性: - **`object` 关键字**:定义全局唯一的单例对象,无需实例化,直接通过名称访问成员。 - **程序入口**:Scala程序的入口 `main` 方法必须定义在单例对象中。 示例: ```scala object PhoneNumberIdentify { // 单例对象内的方法可直接调用 def identify(segment: String): Unit = { println("识别逻辑") } // 程序入口,Scala程序从main方法启动 def main(args: Array[String]): Unit = { identify("133") // 直接调用单例对象内的方法 } } ``` **与C语言的对比**: - C语言的全局函数可直接调用(如 `func()`),Scala通过单例对象的名称调用(如 `PhoneNumberIdentify.identify("133")`)。 - 若方法定义在单例对象内部(与 `main` 平级),可省略对象名直接调用(如示例中的 `identify("133")`)。 ## 四、手机号码类型识别实现 ### 1. 准备号段数组 ```scala val telecomSegments = Array("133", "153", "177") val mobileSegments = Array("134", "135", "136") val unicomSegments = Array("130", "131", "132") ``` ### 2. 定义识别函数(在单例对象内) ```scala def identify(segment: String): Unit = { if (telecomSegments.contains(segment)) { println("中国电信") } else if (mobileSegments.contains(segment)) { println("中国移动") } else if (unicomSegments.contains(segment)) { println("中国联通") } else { println("暂不支持") } } ``` ### 3. 主方法调用 ```scala def main(args: Array[String]): Unit = { identify("133") // 直接调用单例对象内的方法 } ``` ## 五、代码完整示例 ```scala object PhoneNumberIdentify { // 定义各运营商号段数组 val telecomSegments = Array("133", "153", "177") val mobileSegments = Array("134", "135", "136") val unicomSegments = Array("130", "131", "132") // 定义识别函数(与main平级) def identify(segment: String): Unit = { if (telecomSegments.contains(segment)) { println("这个号码是属于中国电信的") } else if (mobileSegments.contains(segment)) { println("这个号码是属于中国移动的") } else if (unicomSegments.contains(segment)) { println("这个号码是属于中国联通的") } else { println("暂不支持该号段识别") } } // 程序入口 def main(args: Array[String]): Unit = { identify("133") // 直接调用单例对象内的方法 } } ``` ## 六、总结 通过案例,我们掌握了Scala的数组、函数与单例对象语法: 1. **数组**:Scala默认不可变,通过 `Array` 类创建,与C语言数组逻辑一致。 2. **函数**:强制声明返回类型,`Unit` 对应C语言的 `void`。 3. **单例对象**:封装全局逻辑,替代C语言的全局函数,提升代码组织性。 Scala语法虽与C语言有差异,但核心逻辑相通,结合C语言基础理解更轻松!帮我整理成博客的格式
最新发布
03-08
<think>嗯,用户让我把关于Scala实现手机号码类型识别的讲解整理成博客格式。首先,我需要回顾用户提供的原始内容,确保所有要点都被涵盖。用户特别提到了要对比C语言,这对于零基础学过C的学习者来说很重要,所以需要保持对比的结构。 接下来,检查结构是否清晰。用户已经分好了章节,比如数组基础、函数定义、单例对象、实现步骤等。可能需要确认每个部分的过渡是否自然,尤其是对比部分是否明确。例如,在数组部分,用户比较了C和Scala的数组定义,我需要确保这些对比明显,并用代码示例支持。 然后,注意格式问题。用户提到所有行内数学表达式要用$...$,但这里的内容主要是代码和语法,可能用不上数学公式。不过要确保代码块正确使用反引号和缩进。例如,Scala的数组定义和函数语法是否正确展示,是否有语法高亮? 另外,用户要求使用单例对象,这部分需要强调与C语言全局函数的区别。可能需要进一步解释单例对象的概念,比如它是如何封装方法,避免全局命名冲突,提高代码组织性。同时,检查示例代码中的单例对象PhoneNumberIdentify是否正确实现,特别是main方法的位置。 在手机号识别实现部分,用户提供了号段数组和识别函数,需要确认逻辑是否正确。例如,使用Array的contains方法是否合适,是否有更高效的数据结构(比如Set)可以考虑,但用户可能为了简单保持数组,所以按用户提供的代码处理。 最后,总结部分需要简明扼要,回顾重点,并鼓励读者结合C语言基础来学习Scala。同时,检查整个博客的流畅性,确保步骤清晰,适合零基础学习者理解。 可能需要注意的中文表达是否正确,比如“号段”是否正确,代码注释是否用中文,以及输出信息是否符合中文习惯。例如,输出“中国电信”而不是“China Telecom”。 还要确保所有代码示例正确无误,比如Scala的语法是否正确,特别是单例对象的定义和main方法的参数。例如,def main(args: Array[String]): Unit是否正确。 现在,整理成博客时可能需要适当增加引言和过渡语句,让读者更容易跟随。例如,在每部分开头简要说明学习目标,或者在对比C和Scala时解释为什么Scala这样做更有优势。 总之,确保结构清晰,代码正确,对比明确,语言流畅,符合中文读者的习惯。</think>```markdown # Scala实现手机号码类型识别:从C语言基础到实战 作为学过C语言的零基础学习者,我们来看看Scala中如何实现手机号码类型识别。本文会结合C语言基础,对比介绍Scala的数组、函数与单例对象语法,再完成功能实现。 --- ## 一、Scala数组基础(对比C语言) 在C语言中,数组是固定长度、同类型元素的集合,比如 `int arr[5];`。而Scala的数组: - **不可变特性**:默认创建后元素不可变(修改需重新赋值) - **定义方式**:通过 `Array` 类创建 **代码对比**: ```scala // C语言数组定义 // int cArray[3] = {1, 2, 3}; // Scala数组定义 val scalaArray = Array(1, 2, 3) // 自动推断类型为Array[Int] ``` --- ## 二、Scala函数定义语法(对比C语言) C语言中函数定义示例: ```c void func() { ... } // 无返回值 int add(int a, int b) { return a + b; } ``` Scala函数特点: - **`def` 关键字**:定义函数 - **返回类型声明**:强制显式声明(递归函数除外) - **无返回值时**:使用 `Unit`(类似C的`void`) **函数定义结构**: ```scala def 函数名(参数: 参数类型): 返回类型 = { // 函数体 } ``` **示例**: ```scala def identify(segment: String): Unit = { // 无实际返回值,用Unit } ``` --- ## 三、Scala单例对象(对比C语言全局函数) C语言通过全局函数实现跨文件调用: ```c void logMessage() { printf("Hello"); } ``` Scala使用单例对象: - **`object` 关键字**:定义全局唯一的对象 - **程序入口**:`main` 方法必须定义在单例对象中 **示例**: ```scala object PhoneNumberIdentify { def identify(segment: String): Unit = { println("识别逻辑") } def main(args: Array[String]): Unit = { identify("133") // 直接调用内部方法 } } ``` **对比说明**: - C语言全局函数直接调用:`func()` - Scala通过单例对象调用:`PhoneNumberIdentify.identify("133")` --- ## 四、手机号码类型识别实现 ### 1. 准备号段数组 ```scala val telecomSegments = Array("133", "153", "177") // 电信 val mobileSegments = Array("134", "135", "136") // 移动 val unicomSegments = Array("130", "131", "132") // 联通 ``` ### 2. 定义识别函数 ```scala def identify(segment: String): Unit = { if (telecomSegments.contains(segment)) { println("中国电信") } else if (mobileSegments.contains(segment)) { println("中国移动") } else if (unicomSegments.contains(segment)) { println("中国联通") } else { println("暂不支持") } } ``` ### 3. 主方法调用 ```scala def main(args: Array[String]): Unit = { identify("133") // 输出:中国电信 identify("131") // 输出:中国联通 identify("188") // 输出:暂不支持 } ``` --- ## 五、完整代码示例 ```scala object PhoneNumberIdentify { // 定义号段数组 val telecomSegments = Array("133", "153", "177") val mobileSegments = Array("134", "135", "136") val unicomSegments = Array("130", "131", "132") // 识别函数 def identify(segment: String): Unit = { if (telecomSegments.contains(segment)) { println("这个号码属于中国电信") } else if (mobileSegments.contains(segment)) { println("这个号码属于中国移动") } else if (unicomSegments.contains(segment)) { println("这个号码属于中国联通") } else { println("暂不支持该号段识别") } } // 程序入口 def main(args: Array[String]): Unit = { identify("133") identify("136") } } ``` --- ## 六、总结与对比 | 特性 | C语言 | Scala | |-----------|--------------------|---------------------| | **数组** | `int arr[5]` | `Array[Int]` | | **函数定义** | `int add() { ... }`| `def add(): Int = { ... }` | | **全局逻辑** | 全局函数 | 单例对象 | **学习要点**: 1. Scala数组默认不可变,需重新赋值修改 2. 函数必须声明返回类型(`Unit` 对应 `void`) 3. 单例对象替代全局函数,增强代码封装性 通过结合C语言基础,可以更快掌握Scala的核心语法逻辑!🎯
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值