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 
    

    完结!!

  • 相关阅读:
    MKMapVIew学习系列2 在地图上绘制出你运行的轨迹
    WPF SDK研究 Intro(6) WordGame1
    WPF SDK研究 Intro(3) QuickStart3
    WPF SDK研究 Layout(1) Grid
    WPF SDK研究 目录 前言
    WPF SDK研究 Intro(7) WordGame2
    WPF SDK研究 Layout(2) GridComplex
    对vs2005创建的WPF模板分析
    WPF SDK研究 Intro(4) QuickStart4
    《Programming WPF》翻译 第6章 资源
  • 原文地址:https://www.cnblogs.com/wqbin/p/12934663.html
Copyright © 2011-2022 走看看