Scala学习笔记(12)-特质、包和引用

1.特质:trait是Scala里代码复用的基础单元。特质封装了方法和字段的定义,并可以通过混入到类中重用它们。不像类的继承那样,每个类都只能继承唯一的超类,类可以混入任意个特质。一旦特质被定义了,就可以使用extends或with关键字,把它混入到类中。Scala程序员“混入”特质而不是继承它们,因为特质的混入与那些其它语言中的多继承有重要的差别。

特质就像是带有具体方法的Java接口,不过其实它能做的更多。特质可以,比方说,声明字段和维持状态值。实际上,你可以用特质定义做任何用类定义做的事,并且语法也是一样的,除了两点。第一点,特质不能有任何“类”参数,也就是说,传递给类的主构造器的参数。换句话说,尽管你可以定义如下的类: 

class Point(x: Int, y: Int) 
但是下面定义特质的尝试将遭到失败:
trait NoPoint(x: Int, y: Int) // 编译不过

类和特质的另一个差别在于不论在类的哪个角落,super调用都是静态绑定的,在特质中,它们是动态绑定的。

2.包

Scala里把代码放在包里的另一种方式很像C#的命名空间。在package子句之后用大括号包起来一段要放到包里去的定义。除此之外,这种语法还能让你把文件的不同部分放在不同的包里。

package bobsrockets.navigation {
    // 在bobsrockets.navigation包里
    class Navigator package tests {
        // 在bobsrockets.navigation.tests包里 class NavigatorSuite
    }
}

正如注释所提示的,Scala的包的确是嵌套的。也就是说,包navigation从语义上在包bobsrockets内部。Java包,尽管是分级的,却不是嵌套的。在Java里,在你命名一个包的时候,你必须从包层级的根开始。Scala为了简化语言使用了更严谨的规则。

3.引用

// 易于访问bobsdelights的所有成员

import bobsdelights._

Scala的按需引用写作尾下划线(_)而不是星号(*)(毕竟*是合法的Scala标识符!

Scala引用可以出现在任何地方,而不是仅仅在编译单元的开始处。同样,它们可以指向任意值。例如:

def showFruit(fruit: Fruit) {
    import fruit._
    println(name +"s are "+ color)//这里的两个索引等价于fruit.name和fruit.color
}

Scala的引用同样可以重命名或隐藏成员。可以用跟在引用的成员对象之后的包含在括号里的引用选择子句:import selector clause做到。下面是一些例子:

import Fruits.{Apple, Orange}

这次只引用了对象Fruits的Apple和Orange成员。

import Fruits.{Apple => McIntosh, Orange}

这次从对象Fruits引用了Apple和Orange两个成员。不过,Apple对象重命名为McIntosh。因此这个对象可以用Fruits.Apple或McIntosh访问。重命名子句的格式是“<原始名> => <新名>”。

import Fruits.{_}

这个引用了对象Fruits的所有成员。这与import Fruits._同义。

import Fruits.{Apple => McIntosh, _}

这个从Fruits对象引用所有成员,不过重命名Apple为McIntosh。

import Fruits.{Pear => _, _}

这个引用了除Pear之外的所有Fruits成员。“<原始名> => _”格式的子句从被引用的名字中排除了<原始名>。某种意义上来说,把某样东西重命名为‘_’就是表示把它隐藏掉。

总而言之,引用选择可以包括下列模式:
 简单名x。把x包含进引用名集。
 重命名子句x => y。让名为x的成员以名称y出现。
 隐藏子句x => _。把x排除在引用名集之外。
 全包括‘_’。引用除了前面子句提到的之外的全体成员。如果存在全包括,那么必须是引用选择的最后一个。

4.私有成员

class Outer {
    class Inner {
        private def f() {
        println("f")
        }
        class InnerMost {
            f() // OK
        }
    }
    (new Inner).f() // 错误:f不可访问
}

Scala里,(new Inner).f()访问非法,因为f在Inner中被声明为private而访问不在类Inner之内。相反,类InnerMost里访问f没有问题,因为这个访问包含在Inner类之内。Java会允许这两种访问因为它允许外部类访问其内部类的私有成员。

Scala里的访问修饰符可以通过使用修饰词增加。格式为private[X]或protected[X]的修饰符表示“直到”X的私有或保护,这里X指代某些外围的包,类或单例对象。

5.伴生对象

在Scala里没有静态成员;代之以可以拥有包含成员的仅存在一个的伴生对象。

Scala的访问规则给予了伴生对象和类一些特权。类把它所有的访问权限共享给半生对象,反过来也是如此。特别的是,对象可以访问所有它的伴生类的私有成员,就好象类也可以访问所有伴生对象的私有成员一样。

你可能感兴趣的:(Scala学习笔记(12)-特质、包和引用)