06_Scala_packages_包

举报
alexsully 发表于 2021/05/04 12:32:37 2021/05/04
【摘要】 Scala包 子包可以直接使用父包 父包使用子包需要import 包对象_解决包里不能有变量/方法问题 包对象_位置和名称 包的访问控制 默认,private,protected 包的引入

包  实际上就是创建不同的文件夹来保存类文件

  1. 区分不同的类名
  2. 管理类
  3. 控制访问范围  
  4. 可以对类的功能进行扩展

Java:包名源码所在的系统文件目录结构要一致译后的字节码文件路径也和包名保持一致

Scala: 包名源码所在的系统文件目录结构要可以不一致,但是编译后的字节码文件路径和包名会保持一致(由编译器完成)

命名规范: com.公司名.目名.业务模块名   com.xxxx.oa.model, com.xxx.oa.controller

Scala会自动引入的常用包 java.lang.*   scala,  Predef

1) 使用package打包,例 如上图

2) 包中有包(嵌套)好处是:可以在同一个文件中,将(class / object)trait 创建在不同的包中,非常灵活

3)作用域原则:可以直接向上访问: Scala中子包中直接访问父包中的内, 号体现作在子包和父包 类重名时,默认采用就近原则,如果希望指定使用某个类,则带上包名即

4) 父包要访问子包的内容时,需要import对应的类等

5)可以在同一个.scala文件中,声明多个并列的package(建议嵌套的pakage不要超过3

6) 包名可以相对也可以绝对,比如,访问BeanProperty的绝对路径是:_root_. scala.beans.BeanProperty ,一般情况下:我们使用相对路径来引入包,只有当包名冲突时,使用绝对路径来处理

// 生成了 scala包 Person.class TestAlex$.class TestAlex.class user.class
// user.class
// scala_new 包 user.class employee.class

package com.alex { //包 com.alex
  
  class user { // com.alex 下创建 user 类
    def hello: Unit = {
      //父包要访问子包的内容时,需要import对应的类
      import com.alex.scala_new.employee //  //想使用 com.alex.scala_update包下的 employee, 或者
      val employee = new employee()

    }

  }

  package scala_new {
    class user { //包 com.alex.scala_new 下创建user类

    }
    class employee{}
  }

  package scala { //包 com.alex.scala
    class  user{
  }

    class Person {
      val name = "Alex"
      def play(message: String): Unit = {
        println(this.name + " " + message)

      }
    }

    object TestAlex { ////包 com.alex.scala 下 创建 object TestAlex
      def main(args: Array[String]): Unit = {
        println("ok")
        //可以直接使用父包的内容
        //1.如果有同名的类,则采用就近原则来使用内容(比如包)
        //2.如果就是要使用父包的类,则指定路径即可
        val user = new user()  //user = OOP.packages.com.alex.scala.user@11531931
        println("user = " + user)
        val user_new = new com.alex.scala_new.user()
        println("user_new = " + user_new) //user_new = OOP.packages.com.alex.scala_new.user@5e025e70
        val employee = new com.alex.scala_new.employee() //OOP.packages.com.alex.scala_new.employee@1fbc7afb
        println(employee)
      }
    }
  }
}


class Mr(var name: String) {
  //第一种形式 [使用相对路径引入包]
  @BeanProperty var age: Int = _
  //第二种形式, 和第一种一样,都是相对路径引入
  @scala.beans.BeanProperty var age2: Int = _
  //第三种形式, 是绝对路径引入,可以解决包名冲突 从根路径开始,很少使用
  @_root_.scala.beans.BeanProperty var age3: Int = _
}


包对象

可以包含类、对象和特质trait,但不能包含函/方法或变量的定义。这是JVM的局限。而scala提供了包对象来解决

  1. 创建包对象后,在该包下生成 public final class package public final class package$
  2. 通过 package$ 的一个静态实例完成对包对象中的属性和方法的调用
  3. 每个包都可以仅有一个包对象 在父包中定义它  (包对象和包是平级的)
  4. 对象称需要和包名一致,一般用来对包的功能补充

package com.alex2 { //包 com.alex2
  
  package scala_new {

    class user { //包 com.alex2.scala_new 下创建user类
    }
    class employee{
    }
    object  test100{
      def main(args: Array[String]): Unit = {
        println( "name: " + name)
        hello()
      }
    }
  }
  //说明
  //1. 在包中直接写方法,或者定义变量,就错误==>使用包对象的技术来解决
  //2. package object scala_new 表示创建一个包对象 scala_new, 他是 com.alex2.scala_new这个包对应的包对象
  //3. 每一个包都可以有一个包对象
  //4. 包对象的名字需要和子包一样 package object scala_new &  package scala_new
  //5. 在包对象中可以定义变量,方法
  //6. 在包对象中定义的变量和方法,就可以在对应的包中使用
  //7. 在底层这个包对象会生成两个类 package.class  和 package$.class (name & hello 进行了二次封装)
  package object scala_new{   // 在父包 com.alex2 中定义
    var name: String = "alex"
    def hello():Unit = {print(name )}
 }
}

Java 四种访问修饰符范围 (修饰符可以 修饰类中的属性,成员方法以及类 【默认/public才能修饰类, protected 子类可以不在同一个包)   

访问级别 修饰符 同类 同包 子类 不同包
1 公开 public
2 保护 protected ×
3 默认 default × ×
4 私有 private × × ×


修饰符 Scala 可见性
默认属性

当属性访问权限为默认时,从底层是private,但提供了xxx_$eq()[类似setter]/xxx()[类似getter] 方法,因此何地方都可以访问)

默认方法
当方法访问权限为默认时,默认为public访问权限
private
private为私有权限,只在类的内部伴生对象中可
protected
protected为受保护权限,更严格,只能子类访问,同包无法访
无public scala中没有public关键字,不能用public显式的修饰属性和方法
包权限 包访问权限(表示属性有了限制。同时包也有了限制) 相当于给访问权限扩大范围


object Vist {
  def main(args: Array[String]): Unit = {
    val person = new Person
    person.name  // 可以访问  private [packages]
    person.name_new  //可以访问 protected[packages]

    val aa = new AA
    // aa.sal  // 报错 private 无法访问,只能在本类内部/伴生对象 使用,要使用需要 private[包名]
  }

}
// 当一个文件同时出现 class AA  object AA , 称object AA 伴生对象, class AA 伴生类, 可以理解为静态 static(Scala理解 static是非对象的)
// 将非静态的部分 放在伴生类中,静态内容放在伴生对象中
class AA {
  var name: String = "alex"  //底层也是私有的,但是生成了可读可写的方法
  private var sal: Double = 9999.9  // 底层私有,但是仅仅生成了可读方法
  protected var age = 10
  var job : String = "大数据工程师"   // 不需要显性使用public,但是底层提供了get  set 方法

  def showInfo(): Unit = {
    //在本类可以使用私有的
    println(" name " + name + " sal= " + sal)
  }

}

object  AA {
  def test(a: AA): Unit = {
    //这里体现出在伴生对象中,可以访问private a.sal
    println("test() name=" + a.name + " sal= " + a.sal)
  }

}
  class Person {
    //这里我们增加一个包访问权限
    //下面private[visit] : 1,仍然是private 2. 在vist包(包括子包)下也可以使用name ,相当于扩大访问范围
   //下面private[packages] : 1,仍然是private 2. 在packages包(包括子包)下也可以使用name ,相当于扩大访问范围
    private [packages] val name = "alex"
    protected[packages] val name_new = "bob"
  }


Scala 引包 details 

import语句可以出现在任何地方,并不仅限于文件顶部,import语句作用直延伸到包含该语句的块末尾。好处是:在需要时在引入包,缩小import 包的作用范围,提高效率

Java中如果想要导入包中所有的类,可以通过通配符*,Scala中采用下 _ 

果不想要某个包中全部的类,而是其中的几个类,可以采用选取(import scala.collection.mutable.{HashMap, HashSet}

如果引入的多个包中含有相同的类,那么可以将不需要的类进行重命名进行区分,这个就是重命名 

import java.util.{ HashMap=>JavaHashMap, List}


果某个冲突的类根本就不会用到,那么这个类可以直接隐藏掉 import java.util.{ HashMap=>_, _}

import scala.beans._ //_表示将该包的所有内容引入,等价 *
object TestImport {
  def main(args: Array[String]): Unit = {

  }
}

class User {
  import scala.beans.BeanProperty //在需要时才引入,作用域在{}
  @BeanProperty var  name : String = ""

  def test(): Unit = {
    //可以使用选择器,选择引入包的内容,这里,我们只引入 HashMap, HashSet
    import scala.collection.mutable.{HashMap, HashSet}
    var map = new HashMap()
    var set = new HashSet()
  }

  def test2(): Unit = {
    //下面的含义是 将 java.util.HashMap 重命名为 JavaHashMap
    import java.util.{ HashMap=>JavaHashMap, List}
    import scala.collection.mutable._
    var map = new HashMap() // 此时的HashMap指向的是scala中的HashMap
    var map1 = new JavaHashMap(); // 此时使用的java中hashMap的别名

  }
  
  def test3: Unit = {
  import java.util.{ HashMap=>_, _} // 含义为 引入java.util包的所有类,但是忽略 HahsMap类.  第一个 _ 代表吧hashmap 隐藏掉,第二个 _ 代表把其它引入
  var map = new HashMap() // 此时的HashMap指向的是scala中的HashMap, 而且idea工具,的提示也不会显示java.util的HashMaple 

  }

}
class Uesr_new {

  @BeanProperty var  name : String = "" // 不可以直接引用,要么{}中再次引用,要么提到最上面统一引入
}

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。