3.包和引入

作者: java大数据编程 | 来源:发表于2018-09-09 16:36 被阅读2次

    包的作用和定义

    同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)
        })
      }
    

    相关文章

      网友评论

        本文标题:3.包和引入

        本文链接:https://www.haomeiwen.com/subject/lukdgftx.html