ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

scala面向对象基础---类继承和特质

2021-07-30 10:06:55  阅读:331  来源: 互联网

标签:特质 混入 scala trait --- 面向对象 extends 超类 class


一、类继承

传送门Scala基础—类继承

  1. Scala的类继承
  2. 调用超类的构造方法
  3. 重写超类的成员
    3.1.不被继承的成员
    3.2.不可重写的成员
    3.3.无参方法与字段
  4. 子类型多态与动态绑定
  5. 抽象类
  6. 关于多重继承
  7. Scala类的层次结构

二、特质介绍

因为Scala没有多重继承,为了提高代码复用率提出了特质的概念,在定义上它主要有以下几个特点(结合单例对象):

  • 特质用关键字“trait”为开头来定义的,它与单例对象很像,两者都不能有入参。但是,单例对象天生就是具体的,特质天生就是抽象的,不过不需要用“abstract”来说明
  • 因为特质是抽象的,所以可以包含抽象成员(成员可以全是抽象,或者全是具体,或者有抽象也有具体),而单例对象却不行。
  • 两者都不能用new来实例化,因为特质是抽象的,而单例对象已经是具体的对象。
  • 类、单例对象和特质三者一样,内部可以包含字段和方法,甚至包含其他类、单例对象、特质的定义。

在混入特质时它有以下几个特点:

  • 特质可以被其它类、单例对象和特质**“混入”**。这里使用术语“混入”而不是“继承”,是因为特质在超类方法调用上采用 线性化机制 ,与多重继承有很大的区别。其它方面,“混入”和“继承”其实是一样的。例如,某个类混入一个特质后,就包含了特质的所有公有成员,而且也可以用“override”来重写特质的成员。

  • Scala只允许继承自一个类,但是对特质的混入数量却没有限制,故而可用于替代多重继承语法。而且对于类的继承必须写在最前面,不能先混入特质,然后再继承类。

  • 要混入一个特质,可以使用关键字“extends”。但如果“extends”已经被占用了,比如已经拿去继承一个类或混入一个特质,那么后续则通过关键字“with”来混入其他特质。也即混入特质既可以使用“extends”,也可以使用with

  • extends只能使用一次,且是用在最前面,但是with可以使用多次。

	class MyClass{
      val c = "Alex"
      val print = () => println(c)
    }


    trait A {
      val absA : String
      private val a = "Trait A"
    }

    trait B {
      val b = "Trait B"
    }
   
    class sub extends MyClass with A with B{
      val absA = "absA"//抽象成员加不加override都可以重写

      override val a = "wzx"//出错,私有成员访问不到

      val myprint = () => println(b,c)
    }

再看一下几种错误的写法!!!
在这里插入图片描述

三、特质的层次

  • 前面已经说过,不止class、objecttrait也可以继承自其他class,或混入任意个trait,这样该特质就是关键字“extends”引入的那个类/特质的子特质,注意只有使用extends才能成为子特质,也即with一个特质不能称为该特质的子特质。
  • 如果没有继承和混入,那么这个trait就是AnyRef类的子特质。当某个class、object或trait混入一个trait时,会隐式继承自这个trait的超类
  • 也就是说,类/单例对象/特质的超类,都是由“extends”引入的类或混入的特质决定的。具体理解一下就是:extends引入类,那么这个类就是超类,这是肯定的;如果混入特质,并且特质使用extends继承了一个类, 那么这个类会自动成为所有混入该特质的超类。

不过混入特质时有一个限制条件:那就是要混入该特质的类/单例对象/特质,它的超类必须是待混入特质的超类,或者是待混入特质的超类的子类。因为特质是多重继承的替代品,那就有“继承”的意思。既然是继承,混入特质的类/单例对象/特质的层次,就必须比待混入特质的层次要低。例如:

scala> class A
defined class A

scala> class B extends A
defined class B

scala> class C
defined class C

scala> trait D extends A
defined trait D

scala> trait E extends B
defined trait E

scala> class Test1 extends D
defined class Test1

scala> class Test2 extends A with D
defined class Test2

scala> class Test3 extends B with D
defined class Test3

scala> class Test4 extends C with D
<console>:13: error: illegal inheritance; superclass C
 is not a subclass of the superclass A
 of the mixin trait D
       class Test4 extends C with D
                                  ^

scala> class Test5 extends A with E
<console>:13: error: illegal inheritance; superclass A
 is not a subclass of the superclass B
 of the mixin trait E
       class Test5 extends A with E
  • 类Test1直接混入特质D,这样隐式继承自D的超类——类A,所以合法。
  • 类Test2继承自类A,A是D的超类,所以也允许混入特质D。
  • 类Test3继承类A的子类B,A是D的超类,所以也允许混入特质D。
  • 类Test4的超类是C,而C与A没有任何关系,所以非法。
  • 类Test5的超类是A,特质E的超类是B,首先A不是E的超类B的子类;其次,虽然E的超类是B,B的超类是A,但是仍然没有符合A是E的超类这个条件。因为Scala没有多继承,所以你可以理解为超类的超类不能成为超类。

四、混入特质的简便方法

如果想快速构造一个混入某些特质的实例,可以使用如下语法:

new Trait1 with Trait2 ... { definition }

这其实是定义了一个匿名类,这个匿名类混入了这些特质,并且花括号内是该匿名类的定义。然后使用new构造了这个匿名类的一个对象,其等效的代码就是:

class AnonymousClass extends Trait1 with Trait2 ... { definition }

new AnonymousClass

除此之外,还可以在最前面加上一个想要继承的超类:

new SuperClass with Trait1 with Trait2 ... { definition }

四、子类型

一个类或者单例对象,如果混入了一个特质(extends和with都行),那么它们就是该特质的子类型。凡是需要特质的地方,都可以由该特质的子类型来替换。

import scala.collection.mutable.ArrayBuffer

trait Pet {
	val name: String
}
class animal

object Dog extends  Pet {
	val name: String = "Harry"
}
class Cat(val name: String) extends animal with Pet

val cat = new Cat("Sally")

val animals = ArrayBuffer.empty[Pet]
animals.append(Dog)
animals.append(cat)
animals.foreach(pet => println(pet.name))  // Prints Harry Sally

标签:特质,混入,scala,trait,---,面向对象,extends,超类,class
来源: https://blog.csdn.net/qq_39507748/article/details/119144579

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有