zoukankan      html  css  js  c++  java
  • Scala核心编程_第07章 面向对象编程(中级部分)

    scala包

    回顾-Java包的三大作用

    1. 区分相同名字的类
    2. 当类很多时,可以管理类
    3. 控制访问范围

    回顾-Java打包与导入包

    打包基本语法

    package com.公司名.项目名;

    打包的本质分析

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

    语法: import 包;

    import java.awt.*;
    import java.util.Scanner;

    引入一个包的主要目的是要使用该包下的类,或者通配符表示所有类。

    Scala包的特点概述

    基本语法 package 包名

    Scala包的三大作用(和Java一样)

    1. 区分相同名字的类
    2. 当类很多时,可以很好的管理类
    3. 控制访问范围

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

    Scala包的命名

    命名规则:

    只能包含数字、字母、下划线、小圆点.,但不能用数字开头, 也不要使用关键字。

    package com.xgo.class. //错误 , 因为class是关键字
    package com.xgo.12a // 错误,因为不能以数字开头

    命名规范:

    一般是小写字母+小圆点一般是
    com.公司名.项目名.业务模块名
    比如:

    com.xgo.oa.model com.xgo.oa.controller
    com.sina.edu.user
    com.sohu.bank.order

    Scala会自动引入的常用包

    java.lang.*

    scala包(Predef在)

    Scala包注意事项和使用细节

    1.scala进行package 打包时,可以有如下形式,三种方式等同。

    代码说明 传统的方式

    package com.xgo.scala
    class Person{
      val name = "wqbin"
      def play(message: String): Unit ={println(this.name + " " + message)
      }
    }
    

    代码说明 :和第一种方式完全等价

    package com.xgo
    package scala
    class Person{
      val name = “wqbin”
      def play(message: String): Unit ={println(this.name + " " + message)
      }
    }
    

    代码说明 :和第一种方式完全等价

    package com.xgo{
      package scala{
        class Person{
          val name = “wqbin"
          def play(message: String): Unit ={println(this.name + " " + message)
          }
        }
      }
    } 
    

    2.包可以嵌套使用。

        可以在同一个文件中,将不同的类(class / object)、trait 创建在不同的包中

    package com.xgo{
        trait Person1{
          val name = “wqbin"
          def play(message: String): Unit ={println(this.name + " " + message)
          }
      package scala{
        class Person2{
          val name = “wqbin"
          def play(message: String): Unit ={println(this.name + " " + message)
          }
        }
      }
    } 
    

    3.作用域原则:可以直接向上访问。

     即: Scala中子包中直接访问父包中的内容, 大括号体现作用域。(提示:Java中子包使用父包的类,需要import)。在子包和父包 类重名时,默认采用就近原则,如果希望指定使用某个类,则带上包名即可。

    package com.xgo{
      //这个类就是在com.xgo
      class User{
      }
      //这个类对象就是在Monster$ , 也在com.xgo
      object Monster {
      }
      class Dog {
      }
      package testpack {
        //这个类就是在com.xgo.scala包下
        class User{
        }
        //这个Test 类对象
        object Test {
          def main(args: Array[String]): Unit = {
            //子类可以直接访问父类的内容
            var dog = new Dog()
            println("dog=" + dog)
            //在子包和父包 类重名时,默认采用就近原则.
            var u = new User()
            println("u=" + u)
            //在子包和父包 类重名时,如果希望指定使用某个类,则带上包路径
            var u2 = new com.xgo.User()
            println("u2=" + u2)
          }
        }
      }
    }
    

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

    package com.xgo{
      //如果要在父包使用到子包的类,需要import
      //引入在com.xgo 包中希望使用到子包的类Tiger,因此需要引入.
      import com.xgo.xgoDemo.Tiger
      //这个类就是在com.xgo
      class User{
      }
      package xgoDemo {
        //Tiger 在 com.xgo.scala 包中
        class Tiger {}}
      object Test2 {
        def main(args: Array[String]): Unit = {
    
          val tiger = new Tiger()
          println("tiger=" + tiger)
        }}}
    

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

    6.包名可以相对引入也可以绝对引入

    比如,访问BeanProperty的绝对路径是:

    _root_. scala.beans.BeanProperty ,在一般情况下:我们使用相对路径来引入包,只有当包名冲突时,使用绝对路径来处理

    package com.xgo
    class Manager( var name : String ) {
      //第一种形式
      //@BeanProperty var age: Int = _
      //第二种形式, 和第一种一样,都是相对路径引入
      //@scala.beans.BeanProperty var age: Int = _
      //第三种形式, 是绝对路径引入,可以解决包名冲突
      @_root_. scala.beans.BeanProperty var age: Int = _
    }
    object TestBean {
      def main(args: Array[String]): Unit = {
        val pm = new Manager("wqbin")
        println("pm=" + pm)
      }}
    

    包对象

    包对象的基本介绍

    包可以包含类、对象和特质trait,但不能包含函数/方法或变量的定义。这是Java虚拟机的局限。为了弥补这一点不足,scala提供了包对象的概念来解决这个问题。

    只要对被修饰的包,同包级别增加一个同名package object包对象就OK,在其中添加 函数/方法或变量的定义。

      package object xxx{
        方法...变量
    }
      package xxx{
    
    }

    package com.xgo {
      //每个包都可以有一个包对象。你需要在父包(com.xgo)中定义它,与被修饰的包同名。
      package object wqbin {
        var name = "wqbin"
    
        def sayOk(): Unit = {
          println("package object sayOk!")
        }
      }
      package wqbin {
        class Test {
          def test(): Unit = {
            //这里的name就是包对象wqbin中声明的name
            println(name)
            sayOk() //这个sayOk 就是包对象wqbin中声明的sayOk
          }
        }
        object TestObj {
          def main(args: Array[String]): Unit = {
            val t = new Test()
            t.test()
            //因为都在包wqbin下,因此也可以使用
            println("name=" + name)
          }
        }
      }
    }

    包对象的底层实现机制分析(重点)

    说明:看反编译代码+分析图

     包对象的本质是在这个包下生成了两个类:

    • public final class package
    • public final class package$

    其中这个public final class package$类含有这个单独维护着这个包的函数/方法或变量的定义。

    scala包的可见性

    回顾-Java访问修饰符基本介绍

    java提供四种访问控制修饰符号控制方法和变量的访问权限(范围):

    • 公开级别:用public 修饰,对外公开
    • 受保护级别:用protected修饰,对子类和同一个包中的类公开
    • 默认级别:没有修饰符号,向同一个包的类公开.
    • 私有级别:用private修饰,只有类本身可以访问,不对外公开.

    回顾-Java中4种访问修饰符的访问范围

     

    Scala中包的可见性介绍:

    在Java中,访问权限分为: public,private,protected和默认。在Scala中,可以通过类似的修饰符达到同样的效果。但是使用上有区别。

    Scala中包的可见性和访问修饰符的使用

    1.当属性访问权限为默认时,默认为public访问权限,但是从底层看属性是private的,但是因为提供了xxx_$eq()[类似setter]/xxx()[类似getter] 方法,因此从使用效果看是任何地方都可以访问。

    class Dog{
      val gender="female"
      var age=5
    }

    2.private为私有权限,只在类的内部和伴生对象中可用 

    class Dog{
      private val gender="female"
      private var age=5
    }

    3.protected为受保护权限,scala中受保护权限比Java中更严格,只能子类访问,同包无法访问 (编译器)

    class Dog{
      var gender="female"
      protected var age=5
    }
    class Ted extends Dog{
      this.age=10 //子类可以访问父类
      this.gender="male"
    }
    
    object TestMain{
    
      def main(args: Array[String]): Unit = {
        var dog=new Dog()
        dog.age//报错==>同包无法访问
        dog.gender="trans"
      }
    } 

    5.在scala中没有public关键字,即不能用public显式的修饰属性和方法。

    6.包访问权限(表示属性有了限制。同时包也有了限制),这点和Java不一样,体现出Scala包使用的灵活性。

    package com.wqbin.scala
    class Person {
      private[scala] val pname="hello" // 增加包访问权限后,1.private同时起作用。不仅同类可以使用 2. 同时com.wqbin.scala中包下其他类也可以使用
    }
    当然,也可以将可见度延展到上层包
    private[wqbin] val description="wang"
    说明:private也可以变化,比如protected[wqbin], 非常的灵活。
    

    scala包的引入

    Scala引入包基本介绍

    Scala引入包也是使用import, 基本的原理和机制和Java一样,但是Scala中的import功能更加强大,也更灵活。

    因为Scala语言源自于Java,所以java.lang包中的类会自动引入到当前环境中,而Scala中的scala包和Predef包的类也会自动引入到当前环境中,即起其下面的类可以直接使用。

    如果想要把其他包中的类引入到当前环境中,需要使用import语言。

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

    class User {
        import scala.beans.BeanProperty
        @BeanProperty var  name : String = ""
    }

    2.导入包中所有的类,Scala中采用通配符 _ ,而Java通过通配符*

    3.如果不想要某个包中全部的类,而是其中的几个类,可以采用选取器(大括号)

    def test(): Unit = {
      import scala.collection._
      import scala.collection.mutable.{HashMap, HashSet}
      var map = new HashMap()
      var set = new HashSet()
    }

    4.如果引入的多个包中含有相同的类,将冲突类进行重命名以区分。=>

    import java.util.{ HashMap=>JavaHashMap, List}
    import scala.collection.mutable._
    var map = new HashMap() // 此时的HashMap指向的是scala中的HashMap
    var map1 = new JavaHashMap(); // 此时使用的java中hashMap的别名

    5.如果某个冲突的类根本就不会用到,那么这个类可以直接隐藏掉。

    import java.util.{ HashMap=>_, _} // 含义为 引入java.util包的所有类,但是忽略 HahsMap类.
    var map = new HashMap() // 此时的HashMap指向的是scala中的HashMap, 而且idea工具,的提示也不会显示java.util的HashMaple 
    

    完结!!

  • 相关阅读:
    关于java异常处理的自我学习
    html学习
    java第七周动手动脑
    作业
    动手动脑
    我要建立自己的java代码仓库
    第三周作业
    day0319 模块
    day0318装饰器和内置函数
    day0315 迭代器
  • 原文地址:https://www.cnblogs.com/wqbin/p/12934663.html
Copyright © 2011-2022 走看看