文章目录
Scala类和对象
类是对象的抽象,对象是类的实现,类是抽象的不占用内存,但对象是具体的内存放在堆里
实现继承:
- 重写加上@Override
- 子类重写超类抽象方法不需要用@Override
- 单一继承
- 只有主构造函数才能往基类构造函数加函数
Scala单例对象:
Scala中没有没有静态方法和静态字段,但是有单例模式,用object关键字修饰被object修饰的类,方法都是静态的。
Scala单例模式除了定义的类,还需要一个object对象,当class取名和object取名相同时,二者互为伴生关系,class为伴生类,object是伴生对象,二者可以互相访问彼此的private,但是无法访问private[this]
1、构造器
Scala中构造分为主构造器和辅助构造器
1、主构造器
一个类只能有一个主构造器,不在任何方法内的代码都属于主构造器
2、辅助构造器
一个类中可以有多个辅助构造器,但是辅助构造器的第一行一定要调用主构造器
注意:代码运行一定是主构造器先运行,在主构造器中没有被任何修饰符修饰的变量默认为privatep[this],如果不用this,默认值是主构造器定义的值。
2、object类
- object是单例的,主构造器代码只执行一次
- 引用类不需要new
3、枚举
Scala枚举和Java差不多,但是不能直接声明,需要继承Enumeration类,并以value调用初始化枚举中的所有可能值:
4、模式匹配
模式匹配是检查某个值是否匹配某一个模式的机制,一个成功的匹配同时会将匹配值解构为其组成部分。它是Java中switch语句的升级版,同样可以用于替代一系列的if/else语句
一个模式匹配语句包括一个待匹配的值,match关键字,以及至少一个case语句
<1>、基本语法
import scala.util.Random
val a: Int = Random.nextInt(5)
a match {
case 0 => "zero"
case 1 => "one"
case 2 => "two"
case _ => "other"
}
<2>、模式识别
abstract class Notification
case class Email(sender: String, title: String, body: String) extends Notification
case class SMS(caller: String, message: String) extends Notification
case class VoiceRecording(contactName: String, link: String) extends Notification
Notification 是一个虚基类,它有三个具体的子类Email, SMS和VoiceRecording,我们可以在这些案例类(Case Class)上像这样使用模式匹配:
showNotification函数接受一个抽象类Notification对象作为输入参数,然后匹配其具体类型。(也就是判断它是一个Email,SMS,还是VoiceRecording)。在case Email(sender, title, _)中,因此对象的sender和title属性在返回值中被使用,而body属性则被忽略,故使用_代替。
上面的理解起来比较简单,下面来看一下守卫:
可以仅匹配类型方法,当不同类型对象需要调用不同方法时,仅匹配类型的模式非常有用,如上代码中MainApp函数对不同类型的M有着不同的表现。一般使用类型的首字母作为case的标识符,例如上述代码中的p和c,这是一种惯例。
abstract class M
case class Phone(model:String) extends M{
def screenOff = "Turn off"
}
case class Computer(model:String) extends M{
def screenON = "Turn on"
}
def MainApp(m:M) = m.match{
case p:Phone => p.screenOff
case c:Computer => c.screenON
}
<3>、InstanceOf
isInstanceOf,判断这个类是否为调用这个方法的子类或者是否是这个类的本身。
asInstanceOf要在isInstanceOf的基础上使用,作用是强转。
<4>、匿名方法
5、Trait
Trait就是接口的意思,使用with进行多继承,使用和Java的接口相同,但是与Java不同点在于:
- 可以定义抽象字段,var定义的不能被重写,val定义的可以被重写,而extends和with同时生效的时候如下面例子:
6、泛型
Scala中声明泛型可以在类上声明,也可以在方法上声明,并且可以指定部分泛型的类型
提一下几个关键的概念:
- 类型上界:比如T <: A这样声明的类型上界表示类型变量T应该是类型A的子类。
- 类型下界:比如T >: A这样声明的类型下界表示类型变量T应该是类型A的父类或者是自己本身。
7、型变
型变是复杂类型的子类型关系与其组件类型的子类型关系的相关性。 Scala支持泛型类的类型参数的型变注释,允许它们是协变的,逆变的,或在没有使用注释的情况下是不变的。 在类型系统中使用型变允许我们在复杂类型之间建立直观的连接,而缺乏型变则会限制类抽象的重用性。
一般地,假设类型C[T]持有类型参数T;给定两个类型A和B,如果满足A <: B,则C[A]与 C[B]之间存在三种关系:
如果C[A] <: C[B],那么C是协变的(Covariant);
如果C[A] :> C[B],那么C是逆变的(Contravariant);
否则,C是不变的(Nonvariant)。
Scala的类型参数使用+标识“协变”,-标识“逆变”,而不带任何标识的表示“不变”
<1>、协变
标志为[+A],将一个泛型类的类型参数A成为协变,成为协变意味着如果有AB两种类型,A是B的子类型,那么List[A]就是List[B]的子类型
abstract class Animal {
def name:String
}
case class Cat(name:String) extends Animal
case class Dog(name:String) extends Animal
这里定义Cat和Dog为Animal的子类型,又因为Scala标准库也定义了List[+A], 所以可以像文档中那样写,运行最后的两个方法:
<2>、逆变
标志为[-A],可以让一个泛型类的类型参数A成为逆变,概念与协变相反,如果A是B的子类型,那么Writer[B] 是Writer[A]的子类型。
除此之外,默认的情况下,就是泛型的不变状态。
8、隐式转换
之前在博客中专门将结果Scala的隐式转换,附上博客地址隐式转换
隐式转换是一个很重要的部分,在这里再简单说明一下:
方法可以具有隐式参数列表,由参数列表开头的 implicit 关键字标记。 如果参数列表中的参数没有像往常一样传递, Scala 将查看它是否可以获得正确类型的隐式值,如果可以,则自动传递。
Scala 将查找这些参数的位置分为两类:
- Scala在调用包含有隐式参数的方法的时候,首先查找可以直接访问的隐式定义和隐式参数
- 然后在伴生对象查找和隐式候选类型相关的隐式标记的成员
Implicit可以将一种数据类型转换为另一种数据类型,并且这种数据类型拥有所有另一种类型的方法,也算作是一种方法的增强。
隐式转换分为两种
- 隐式转换类(方法)
- 隐式转换值
隐式转换方法的形式一般会写成:implicit def AToB(a:A):B={}
意思就是转换一个类型:
隐式转换参数一般会写成:
原文地址:https://blog.csdn.net/weixin_44240370/article/details/98727303
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。