Scala中面向对象编程怎么用

发布时间:2021-07-20 11:44:41 作者:chen
来源:亿速云 阅读:298

这篇文章主要讲解了“Scala中面向对象编程怎么用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Scala中面向对象编程怎么用”吧!

2 面向对象编程

scala在数据的处理上使用的是函数式编程思想,但在上层的架构组织中仍使用面向对象的模型,对于大型应用程序尤其重要。

类的定义

类的声明使用关键字 class:

class Counter{   //这里定义类的字段和方法}

Scala中建议类名首字母大写。

下面来定义一个完整的类:

class Woman{   //定义类的字段val sex = "female"//定义类的方法def usedToBeGirl():Unit = {   println("A Woman used to be a girl.")}}

方法usedToBeGirl()的返回值类型为Unit,代表它没有返回任何结果,是一个空值,表示为()

scala的类允许嵌套定义

类的方法
  1. 方法的调用

    方法若没有参数,在定义时可以省略括号。

    方法定义时若省略了括号,那么调用时也不能带括号;若没有省略括号,则调用时带不带括号都可以。

    比如:

    class MyFather{     //定义类的字段val age = 40val sex = "male"//定义类的方法def getAge():Int = agedef getSex:String = sex}


    这里getAge方法的调用:

    //先创建一个实例val f = new MyFather//以下这两种调用方法都可以f.getAge
    f.getAge()//getSex方法声明时没有括号,调用时也不能有括号f.getSex


  2. 方法的返回值

    方法有声明返回值类型,那么返回值是方法体中最后一条执行语句的值;

    方法没有声明返回值类型,那么scala编译器会根据方法体中最后一条执行语句的值来推断返回值类型。

    此时如果省略了等号,使用大括号,scala编译器会将返回值推断为Unit。

  3. 方法参数

  4. scala中允许方法重载

  5. scala中允许方法的嵌套定义

类成员的可见性

scala类中,所有成员的默认可见性都是公有的,且不需要使用 public 关键字进行限定。

除了public之外,scala也具有和java同样的可见性选项:private和protected。

scala是不推荐将所有成员设置为公有属性的,而建议将其设置为private,这样外部成员就无法直接访问私有字段。因此,像java类中使用的getter和setter方法一样,scala也提供对private 字段进行访问和修改的方法。

class Counter{   //定义一个private字段private var privateValue = 0//提供访问和修改privateValue的方法def value = privateValuedef value_ = (newValue:Int){   if (newValue > 0) privateValue = newValue}   }

其中,value 和value_ 这两个方法是成对的。

访问privateValue字段:

//先实例化一个对象val counter = new Counter//访问privateValuecouner.value//修改privateValuecounter.value_(3)

上面对私有字段进行修改的方法也可以省略下划线_(scala语法规定):

counter.value(3)

这样会显得更加直观。

构造器

在scala中,整个类的定义主体就是类的构造器,称为主构造器,所有位于类方法以外的语句都将在构造过程中被执行。

那么如何向构造器传入参数呢?

scala规定在类名之后使用圆括号列出主构造器的参数列表:

class Counter(name:String){   
  	private val value = 0}

除了主构造器,scala类还可以拥有零个或多个辅助构造器

每个辅助构造器的第一条语句必须是对主构造器或者此前已经定义的辅助构造器的调用。

辅助构造器使用this进行定义,调用形式为:this(参数列表)

对象

单例对象

scala中的单例对象相当于java中的静态成员。

单例对象的定义使用object 关键字:

object Person{   
   private var lastId = 0{      lastId += 1   lastId   }}

单例对象在第一次被访问的时候初始化。

单例对象包括两种:伴生对象和孤立对象。

当一个单例对象具有同名类,则这个单例对象就称为这个同名类的伴生对象。相应的,这个同名类就称为这个单例对象的伴生类。它们之间可以互相访问对方的私有成员。

反之,没有同名类的单例对象,就称为孤立对象。比如scala程序的入口main方法就定义在一个孤立对象里:

object HelloWorld{          //HelloWorld是一个孤立对象def main(args[]:Array[String]){   println("Hello World!")}}

对于包含了伴生类和伴生对象定义的代码文件,不能直接在REPL中使用":load"命令来执行,需要先对其进行编译,再用scala命令来执行。

apply方法

之前的介绍中曾经使用过apply方法:

val strArr = Array("hadoop","spark","flink")

可以看到这里实例化了一个数组对象strArr,但是并没有使用new关键字进行创建,这里实际上就是隐式调用了apply方法。整个过程就是,scala自动调用了Array类的伴生对象Array中一个apply方法,创建了一个Array对象。

class TestApply{   def apply(param:String):Unit = {   println("apply method called " + param)}}

在REPL模式下执行程序:

先创建一个TestApply对象,名为myObject。然后执行myObject("Hello Apply"),传递了一个参数,执行的结果就是类中的apply方法被自动调用了。

scala> val myObject = new TestApply    
val myObject: TestApply = TestApply@3caf5c96scala> myObject("Hello Apply")apply method called Hello Apply

然而我的学识尚浅,有一个疑惑,把apply方法名改成别的还会自动调用该方法吗?

经过我的实验可以证明,答案是:不会。

将TestApply类中的apply方法改名为helloApply,然后重新执行程序:

scala> :load /usr/local/scala/mycode/testApply.scalaval args: Array[String] = Array()Loading /usr/local/scala/mycode/testApply.scala...class TestApply

scala> val myObject = new TestApplyval myObject: TestApply = TestApply@53da2aecscala> myObject("Hello Apply")   ^   error: TestApply does not take parameters

scala> myObject.helloApply("Hello Apply")apply method called Hello Apply

只有显式调用helloApply方法才行。

将类的构造方法以apply方法的形式定义在类的伴生对象中,类的伴生对象就成为了一个“工厂”,专门生产类的实例,apply方法就称为工厂方法

实际上,apply方法设计的初衷就是为了保持对象和函数之间使用的一致性,数学中函数的使用形式是函数(参数),在scala中函数也是对象,因此scala的方法调用可以省去对方法的调用,像使用函数一样使用方法。

函数(参数)函数.方法(参数)

在scala中,apply的调用规则是:用括号传递给类实例或对象名一个或多个参数时,scala会在相应的类或对象中查找名为apply的方法,且要求参数列表与传入参数一致,然后调用该apply方法。

unapply方法

unupply方法用于对对象进行解构操作,它也会被自动调用。

unapply方法可以看做apply方法的反向操作,它从某个类的构造函数中解构出该函数的传入参数。

继承

抽象类

若一个类包含没有实现的成员(字段或方法),那么它就是抽象类,要使用abstract 关键词对该类进行修饰。

abstract class Person{   val name:Stringval age:Intdef getAge()def greeting(){   println("hello")}}

抽象类中的抽象字段必须声明类型。抽象类不能实例化,只能作为父类被其它类继承。

与java不同的是,scala抽象类中的抽象方法不需要加abstract修饰。

类的继承

scala中的继承与java一样,只支持单一继承,即一个子类只能有一个父类。继承父类使用关键字使用extends关键字表示。

定义子类时,需要注意以下几点:

Scala的类层级结构

Scala中面向对象编程怎么用

类型描述
Null所有引用类型的子类。值为null,表示一个空对象。
NothingNothing类型在Scala的类层级的最底端;它是任何其他类型的子类型。
AnyAny是所有其他类的超类
AnyRefAnyRef类是Scala里所有引用类(reference class)的基类
Option类

scala采用Option类来统一表示对象有值和无值的情况,Option是一个抽象类,有一个具体的类Some和一个对象Node。Some表示有值,None表示无值。

参数化类型

scala中的参数化类型相当于java中的泛型,与之不同的是scala中使用方括号[] 来定义参数化类型。

特质 Trait

scala中的特质Trait 相当于java中的接口。一个特质被子类实现以后,就可以看做这个类的父类,但与继承不同的是,特质允许多重实现,也就是一个子类可以混入多个特质。

特质可以同时用拥有具体方法和抽象方法,这就跟抽象类很相似。

注:

模式匹配

  1. match 语句

    scala中最常见的模式匹配是match语句,类似于其它语言中的switch语句。

    val grade = 90grade match {     case 'A' => println("85-100")case 'B' => println("70-84")case 'C' => println("60-69")case _ => println("unqualified!")}


    最后一个case使用了下划线"_"代表其它情况,相当于java中的default分支。

  1. case 类

    定义一个类时,如果在class关键字前加上case修饰,则该类为case类。scala为case类重载了许多实用的方法,包括tiString,equals和hashcode方法。更重要的是,scala为每一个case类自动生成一个伴生对象。

为了解决程序中的命名冲突,scala也和java一样使用包来层次化、模块化地组织程序。

将代码放在指定包中的两种方法:

感谢各位的阅读,以上就是“Scala中面向对象编程怎么用”的内容了,经过本文的学习后,相信大家对Scala中面向对象编程怎么用这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

推荐阅读:
  1. Scala中的数组
  2. Scala怎么用

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

scala

上一篇:JavaScript中的继承采用什么方式

下一篇:怎么修改gazebo物理参数

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》