3.包和引入

包的作用和定义

同java中的包,Scala中的包主要用于大型工程代码的组织同时也解决命名冲突的问
题。Scala中的包与java有着诸多的相似之处,但Scala语言中的包更加灵活。

  • 包定义方式一:
//将代码组织到cn.scala.xtwy包中
package cn.scala.xtwy

abstract class Animal {
  //抽象字段(域)
  var height:Int
  //抽象方法
  def eat:Unit
}

class Person(var height:Int) extends Animal{
  override def eat()={
    println("eat by mouth")
  }

}

object Person extends App{
  new Person(10).eat()
}

  • 包定义方式二:
    //下面的代码定义了一个cn.scala.xtwy包
    //在程序的任何地方都可以通过cn.scala.xtwy.Teacher来使用Teacher这个类
package cn{
  package scala{
    package xtwy{
      class Teacher {

      }
    }
  }
}

可以看出,我们可以在任何地方进行包中类的定义,scala帮助我们进行自动文件组织
我们将Teacher.scala内容修改如下:

package cn{
  package scala{
    package xtwy{
      class Teacher {

      }
    }
  }
}

//添加了cn.scala.spark包,包中定义了一个SparkDemo类

package cn{
  package scala{
    package spark{
      class SparkDemo{

      }
    }
  }
}

通过前面的介绍,我们知道了如何定义包,包是怎么组织代码的。在实际开发过程当中,尽量使用java包的定义方式并将代码集中进行管理,这样别人读代码的时候更方便,代码更简洁。

包的作用域与引入(import)的使用方法

下面的代码给出了包的作用域和引入的使用方法

package cn{
  package scala{
    //在包cn.scala下创建了一个Utils单例
    object Utils{
      def toString(x:String){
        println(x)
      }
      //外层包无法直接访问内层包,下面这一行代码编译通不过
     //def getTeacher():Teacher=new Teacher("john")
     //如果一定要使用的话,可以引入包
     import cn.scala.xtwy._
     def getTeacher():Teacher=new Teacher("john")
    }
    //定义了cn.scala.xtwy
    package xtwy{
      class Teacher(var name:String) {
           //演示包的访问规则
           //内层包可以访问外层包中定义的类或对象,无需引入
           def printName()={Utils.toString(name)}
      }

    }
  }
}
object appDemo{
        //scala允许在任何地方进行包的引入,_的意思是引入该包下的所有类和对象
        import cn.scala._
        import cn.scala.xtwy._
        def main(args: Array[String]): Unit = {
            Utils.toString(new Teacher("john").name)
            new Teacher("john").printName() 
        }

}

Scala访问修饰符

Scala 访问修饰符分别有:private,protected,public。

如果没有指定访问修饰符符,默认情况下,Scala 对象的访问级别都是 public。

Scala 中的 private 限定符,比 Java 更严格,在嵌套类情况下,外层类甚至不能访问被嵌套类的私有成员。

私有(Private)成员

用private关键字修饰,带有此标记的成员仅在包含了成员定义的类或对象内部可见,同样的规则还适用内部类。

class Outer{
        class Inner{
        private def f(){println("f")}
        class InnerMost{
            f() // 正确
            }
        }
        (new Inner).f() //错误
}

(new Inner).f( )访问不合法是因为f在Inner中被声明为private,而访问不在类Inner之内。

保护(Protected)成员

在scala中,只允许保护成员在定义了该成员的的类的子类中被访问。

package p{
        class Super{
            protected def f() {println("f")}
        }
        class Sub extends Super{
            f()
        }
        class Other{
            (new Super).f() //错误
        }
}

上例中,Sub 类对 f 的访问没有问题,因为 f 在 Super 中被声明为 protected,而 Sub 是 Super 的子类。相反,Other 对 f 的访问不被允许,因为 other 没有继承自 Super。

公共(Public)成员

Scala中,如果没有指定任何的修饰符,则默认为public。这样的成员在任何地方都可以被访问。

class Outer {
       class Inner {
              def f() { println("f") }
              class InnerMost {
                     f() // 正确
              }
       }
       (new Inner).f() // 正确因为 f() 是 public
}

作用域保护

Scala中,访问修饰符可以通过使用限定词强调。格式为:

private[x]

protected[x]

这里的x指代某个所属的包、类或单例对象。如果写成private[x],读作"这个成员除了对[…]中的类或[…]中的包中的类及它们的伴生对像可见外,对其它所有类都是private。

这种技巧在横跨了若干包的大型项目中非常有用,它允许你定义一些在你项目的若干子包中可见但对于项目外部的客户却始终不可见的东西。

package bobsrocckets{
    package navigation{
        private[bobsrockets] class Navigator{
         protected[navigation] def useStarChart(){}
         class LegOfJourney{
             private[Navigator] val distance = 100
             }
            private[this] var speed = 200
            }
        }
        package launch{
        import navigation._
        object Vehicle{
        private[launch] val guide = new Navigator
        }
    }
}

上述例子中,类Navigator被标记为private[bobsrockets]就是说这个类对包含在bobsrockets包里的所有的类和对象可见。

比如说,从Vehicle对象里对Navigator的访问是被允许的,因为对象Vehicle包含在包launch中,而launch包在bobsrockets中,相反,所有在包bobsrockets之外的代码都不能访问类Navigator。

下面给出的是访问规则表

修饰符 访问范围
无任何修饰符 任何地方都可以使用
private[scala] 在定义的类中可以访问,在scala包及子包中可以访问
private[this] 只能在定义的类中访问,即使伴生对象也不能访问团
private 在定义的的类及伴生对象中可以访问,其它地方不能访问
protected[scala] 在定义的类及子类中可以访问,在scala包及子包中可以访问
protected[this] 只能在定义的类及子类中访问,即使伴生对象也不能访问
protected 在定义的类及子类中访问,伴生对象可以访问,其它地方不能访问

包对象

包对象主要用于将常量、工具函数,使用时直接通过包名引用

//下面的代码给出了包对象的定义
package cn.scala.xtwy

//利用package关键字定义单例对象
package object Math {
  val PI=3.141529
  val THETA=2.0
  val SIGMA=1.9
}

class Coputation{
  def computeArea(r:Double)=Math.PI*r*r
}

import高级特性

  • 隐式引入
    在集合那一讲,我们提到,如果不引入任何包,scala会默认引入java.lang._
    scala._
    Predef._
    包中或对象中所有的类和方法,称这种引入会隐式引入
  • 重命名
    scala中允许对引入的类或方法进行重命名,如果我们需要在程序中同时使用java.util.HashMap及scala.collection.mutable.HashMap时,可以利用重命名的方法消除命名冲突的问题,虽然也可以采用包名前缀的方式使用,但代码不够简洁
//将java.util.HashMap重命名为JavaHashMap
import java.util.{ HashMap => JavaHashMap }
import scala.collection.mutable.HashMap
object RenameUsage {
  def main(args: Array[String]): Unit = {
    val javaHashMap = new JavaHashMap[String, String]()
    javaHashMap.put("Spark", "excellent")
    javaHashMap.put("MapReduce", "good")
    for(key <- javaHashMap.keySet().toArray){
      println(key+":"+javaHashMap.get(key))
    }

    val scalaHashMap=new HashMap[String,String]
    scalaHashMap.put("Spark", "excellent")
    scalaHashMap.put("MapReduce", "good")
    scalaHashMap.foreach(e=>{
      val (k,v)=e
      println(k+":"+v)
    })
  }

}
  • 隐藏类
//通过HashMap=> _,这样类便被隐藏起来了
import java.util.{HashMap=> _,_}
import scala.collection.mutable.HashMap


object RenameUsage {
  def main(args: Array[String]): Unit = {

    //这样的话,HashMap便无歧义地指向scala.collection.mutable.HashMap
    val scalaHashMap=new HashMap[String,String]
    scalaHashMap.put("Spark", "excellent")
    scalaHashMap.put("MapReduce", "good")
    scalaHashMap.foreach(e=>{
      val (k,v)=e
      println(k+":"+v)
    })
  }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容

  • Scala与Java的关系 Scala与Java的关系是非常紧密的!! 因为Scala是基于Java虚拟机,也就是...
    灯火gg阅读 3,343评论 1 24
  • 我们排练了很久的童话剧要上演啦!好激动呀,我们十一点多到学校去了,还以为是第一名,当我们来到教室的时候,教室里没有...
    张煜梒阅读 212评论 0 0
  • 没有想过这辈子 要与你相遇 曲径通幽处 你用亿万年的沉默 静静地隐世守候 人生际遇总有些出奇 辗转反侧中 如履薄冰...
    黑油亮阅读 236评论 0 5
  • NSFileManager* manager = [NSFileManager defaultManager]; ...
    今年27阅读 405评论 0 0
  • 感觉自己的性格是有些冷漠的吧,对身边的许多事常常是了然于心而无动于衷。 不知道有多少人和我一样,莫...
    不知其然阅读 111评论 0 0