scala面向对象

一.包嵌套
( 1)一个源文件中可以声明多个 package
( 2)子包中的类可以直接访问父包中的内容,而无需导包
( 3)包对象:在 Scala 中可以为每个包定义一个同名的包对象, 定义在包对象中的成员, 作为其对
应包下所有 class 和 object 的共享变量, 可以被直接访问。
( 4)导包说明

图片.png

(1)scala里的setget: @BeanPropetry

    class Person {
      var name: String = "bobo" //定义属性
      var age: Int = _ // _表示给属性一个默认值
      //Bean 属性( @BeanProperty)
      @BeanProperty var sex: String = "男"
      //val 修饰的属性不能赋默认值,必须显示指定
    }

封装

一.概念
Scala 中的 public 属性,底层实际为 private,并通过 get 方法( obj.field())和 set 方法
( obj.field_=(value))对其进行操作。所以 Scala 并不推荐将属性设为 private,再为其设置
public 的 get 和 set 方法的做法。但由于很多 Java 框架都利用反射调用 getXXX 和 setXXX 方
法,有时候为了和这些框架兼容,也会为 Scala 的属性设置 getXXX 和 setXXX 方法(通过
@BeanProperty 注解实现)

二.访问权限

( 1) Scala 中属性和方法的默认访问权限为 public,但 Scala 中无 public 关键字。
( 2) private 为私有权限,只在类的内部和伴生对象中可用。
( 3) protected 为受保护权限, Scala 中受保护权限比 Java 中更严格,同类、子类可以
访问,同包无法访问

( 4) private[包名]增加包访问权限,包名下的其他类也可以使用

对象

1.自动推导变量类型不能多态,所以多态需要显示声明(?)

2.构造器:Scala包括主构造器和辅助构造器。
注:辅助构造器不能直接构建对象,必须直接或间接调用主构造方法。

3.构造器里的三种参数设置

class Test(name:String,var age:Int,val sex:String) {
  /*
  * name:局部变量
  * age:成员变量
  * sex:只读成员变量
  * */
  var name1:String = name
}

继承和多态

1.scala中属性和方法都是动态绑定

      class a{
        val name:String = "a"
        def hello(): Unit = {
          println("hello a")
        }
      }
      class aSon extends a{
        override val name:String = "aSon"
        override def hello(): Unit = println("hello b")
      }
      object Test{
        def main(args: Array[String]): Unit = {
          var aa = new aSon
          println(aa.name)
          aa.hello()
        }
      }

输出是:aSon ,hello b。如果是java,输出是a,hello b

抽象类

1.重写非抽象方法需要用 override 修饰,重写抽象方法则可以不加 override
2.子类中调用父类的方法使用 super 关键字
3.子类对抽象属性进行实现,父类抽象属性可以用 var 修饰;子类对非抽象属性重写,父类非抽象属性只支持 val 类型,而不支持 var。
因为 var 修饰的为可变变量,子类继承之后就可以直接使用,没有必要重写(但是写var不会报错)

匿名子类

                //Person是抽象类
    val person = new Person {
    override val name: String = "teacher"
    override def hello(): Unit = println("hello teacher")

单例对象(伴生对象)

Scala语言是完全面向对象的语言, 所以并没有静态的操作( 即在Scala中没有静态的概

念) 。但是为了能够和Java语言交互(因为Java中有静态概念),就产生了一种特殊的对象
来模拟类对象, 该对象为单例对象。若单例对象名与类名一致,则称该单例对象这个类的伴
生对象,这个类的所有“静态” 内容都可以放置在它的伴生对象中声明。

说明

( 1)单例对象采用 object 关键字声明

( 2)单例对象对应的类称之为伴生类,伴生对象的名称应该和伴生类名一致。

( 3)单例对象中的属性和方法都可以通过伴生对象名(类名)直接调用访问。

**apply方法**

( 1)通过伴生对象的 apply 方法, 实现不使用 new 方法创建对象。

( 2)如果想让主构造器变成私有的,可以在()之前加上 private。

( 3) apply 方法可以重载。

( 4) Scala 中 obj(arg)的语句实际是在调用该对象的 apply 方法,即 obj.apply(arg)。用
以统一面向对象编程和函数式编程的风格。

( 5)当使用 new 关键字构建对象时,调用的其实是类的构造方法,当直接使用类名构
建对象时,调用的其实时伴生对象的 apply 方法。

特质(接口)

基础
1.所有的 Java 接口都可以当做 Scala 特质使用
2.动态混入:可灵活的扩展类的功能

    val t2 = new Teacher with SexTrait {
                  override var sex: String = "男"
    }
    println(t2.sex)

特质叠加
第一种,一个类( Sub)混入的两个 trait( TraitA, TraitB)中具有相同的具体方法,且两个 trait 之间没有任何关系,解决这类冲突问题,直接在类( Sub)中重写冲突方法

图片.png

第二种,一个类( Sub)混入的两个 trait( TraitA, TraitB)中具有相同的具体方法,且两个 trait 继承自相同的 trait( TraitC),及所谓的“钻石问题”,解决这类冲突问题, Scala采用了特质叠加的策略。


图片.png

注:特质叠加顺序

图片.png

特质自身类型

使用_:Name(with Name)=>this:Name(with Name)=> 将Name类/接口/特质注入

class User(val name: String, val age: Int)
class Dao {
  def insert(user: User) = {
    println("insert into database :" + user.name)
  }
}
trait APP {
  _: Dao =>
  def login(user: User): Unit = {
    println("login :" + user.name)
    insert(user)
  }
}
object MyApp extends Dao with APP{
  def main(args: Array[String]): Unit = {
    login(new User("bobo", 11))

  }
}

特质和抽象类的区别

1.优先使用特质。一个类扩展多个特质是很方便的,但却只能扩展一个抽象类。

2.如果你需要构造函数参数,使用抽象类。因为抽象类可以定义带参数的构造函数,
而特质不行( 有无参构造)

**类型检查和转换
( 1) obj.isInstanceOf[T]:判断 obj 是不是 T 类型。
( 2) obj.asInstanceOf[T]:将 obj 强转成 T 类型。
( 3) classOf 获取对象的类名。

val pClass: Class[Person] = classOf[Person]

枚举类和应用类

// 枚举类
object Color extends Enumeration {
val RED = Value(1, "red")
val YELLOW = Value(2, "yellow")
val BLUE = Value(3, "blue")
}
// 应用类
object test extends App {
//不用main方法就能执行
println(Color.RED)
}

type定义类型
就是给原有类型换个名

  type S = String
  var v:S = "aa"
   //true
  println(v.isInstanceOf[String])
  var v1:String = "aa"
//true
 println(v1.isInstanceOf[S])

你可能感兴趣的:(scala面向对象)