Scala 面向对象

1、Scala 包

Scala也有包,包的命名使用规则和 java 完全一样

1.1、包的声明

  1. package com.scala.day
  2. 在scala 中一个 .scala 文件中一般会写多个类,所有的类会默认在一个包中
    package aa{
    class A
    }
object Pack1{
	  def main(args: Array[String]): Unit = {
	  }
}
class A
package aa{
	class A //两个不在一个包下面
}
   

1.2、包的使用

如何导包和导类:

  1. 在文件的最顶层 import java.util.HashMap
  2. 在代码的任何需要的地方导包,比如方法内部
  3. 通配符导入:
           import java.util._
           import java.util.{HashMap,TreeMap}
           import java.util.{HashMap=>jHashMap}
           import java.util.{HashMap=>_,_}
//import java.util.HashMap 在文件顶层
//import java.util.TreeMap
//import java.util.{HashMap,TreeMap} 同时导多个包
//import java.util._ 通配符导入,将util包下所有类全导入
//import java.util.{HashMap=>jHashMap} 导包时起个别名
//import java.util.{HashMap=>_,_} 屏蔽HashMap其余都想用
object Pack1{
	  def main(args: Array[String]): Unit = {
	  	import java.util.HashMap //在方法内部
	  	new HashMap[String,String]()
	  }
}
class A{
}
package aa{
	class A 
}

1.3、包对象

package object pack{
	def foo(): Unit = println("foo...")
}
object Pack1{
	def main(args: Array[String]): Unit = {
	  	foo()
	 }
}

默认导入:

java:

  1. java.lang.*

scala:
     1) java.lang._
     2) scala._
     3) scala.Predef._

2、类和对象

2.1、定义属性

  • 在 Scala 中,类只要没加 private 的就都是public,且Scala中没有 public 关键字。
  • 定义属性与定义普通变量完全一样
  • 定义的属性在Scala中会自动定义为 private 还会实现getter、setterr 方法,但scala默认的getter、setter不满足标准的的javaBean规范,需要注解(@BeanProperty)加在属性定义前,即会增加标准getter、setter方法,用(@beanGetter)则只加标准getter方法。
object PackDemo {
  def main(args: Array[String]): Unit = {
    val user = new User
    println(user)
    println(user.age)
    println(user.name)
    user.eat()
  }
}
class User{
  //定义属性和定义变量完全一样
  @BeanProperty var age:Int = 10
  var name :String = "李四"
  //给类定义方法
  def eat() = {
    println("eat:" + this.name)
  }

}

2.2、类属性的初始化

1) 类的属性在scala中也可以让虚拟机自动给初始化值,但只能是var,且需要自动给类型,而不是推导。

2) 初始化的值分为三种:

  1. 数字型 0
  2. boolean false
  3. 其他所有类型 null
class User1{
	var age:Int = _
	var name:String = _
	var isExit:Boolean = _
}

2.3、类的构造器

  • 调用构造器创建对象时可以给属性赋值
  • 构造器中里面声明的形参会自动成为类的属性
  • 若 sex(未定义 var、val) 放在构造函数中时(如下)只能内部调用,外部不能用,若内部没人调用,则scala会帮我们自动优化(类似于删掉这个属性),但若内部调用(如下图def eat 中调用了) 则不会被优化。
  • 类名后面跟的其实就是构造器,这个就是主构造器,一个类有唯一的一个。
  • def this() :辅构造器,首行必须调用主构造器,辅构造器中的参数,仅仅是一个只能在当前的这个辅构造器内使用的普普通通的变量
  • 辅构造器中有顺序要求,后面的辅构造器能调用前面的辅构造器,前面的不能调用后面的
  • 主构造器中形参也能使用 @BeanProperty
object obj1{
	def main(agrs: Array[String]) : Unit = {
		var lisi:User2= new User2(age=10,name="lisi",sex="male")
		println(lisi.age)
		val user:User2 = new User
		println(user.age)
	}
}
class User2(@BeanProperty val age:Int,var name:String,sex:String){
	def eat:Unit = {
		println(sex)
	}
	//这种构造器叫做:辅构造器
	//首行必须调用主构造器
	def this(){
		this(10,"abc","male")
	}
	def this(c:Int){ 
		this() //间接调用主构造器
	}
}

2.4、给类起别名

bject obj1{
	def main(agrs: Array[String]) : Unit = {
		type U = User2
		val u:U = new U(age =10,name="a",sex="female")
		println(u.age)
		println(u.getClass.getName) //输出还是 User2
	}
}
class User2(@BeanProperty val age:Int,var name:String,sex:String){
	def eat:Unit = {
		println(sex)
	}
}

3、封装

3.1、权限修饰符

java:

  1. public
  2. protected (同包与子类)
  3. [default] friendly (同包)
  4. private (本类)

scala:

  1. [default] 默认都是 public
  2. protected (只能在子类中使用,同包内不行)
  3. private (本类)

scala 权限修饰的灵活性:可以定制

private[包A] (也可以对属性)
包A和包A的所有子类都可以访问

object Modifier{
	def main(agrs: Array[String]) : Unit = {
		val user:User = new User(age=10)
		//若不开后门,则age这会报错
	}
}
//对主构造器私有
//[modier] 使User类在本包中可以使用,其余的不可以
//modier是包名,可以自行定义(开后门)
class User private[modier](var age:Int){
	private val a:Int = 10
}

4、继承

java:

  1. 类是单继承
  2. 接口 多实现

scala:

  1. 类也是单继承
  2. scala 没有接口,但是是提供了更强大的 trail (特质)
object Extends1{
	def main(args: Array[String]): Unit = {
		val b:B = new B
		b.foo()
	}
}
class A{
	def foo = {
		println("A foo......")
	}
}
class B extends A{
	override def foo() : Unit = { //方法的覆写(重写)
		super.foo() 
		println("B foo...")
	}
}

注意

  • 覆写方法,比较必须添加关键字 override,java 中可有可无

构造器的特征

  • java:父的静态 -> 子的静态 -> 父的构造 -> 子的构造
  • scala:父的主构造 -> 子的主构造 -> 子构造

属性的覆写

  • val 只能覆写 val 和不带参数的 def
  • var 只能覆写抽象的 var
object Extends1{
	def main(args: Array[String]): Unit = {
		val b1:B = new B
		println(b1.a)
		println(b1.b)
		println(b1.c)
	}
}
class A{
	val a : Int = 10
	var b : Int = 20
	def c : Int = 30
	
}
class B extends A{
	override val a : Int = 20 //可以
	override var b : Int = 30 //运行出错 不可以
	override val c : Int = 40 //可以
}

注意:

  • 在java中,方法有多态,属性没有多态
  • 在scala中,不仅方法有多态,属性也有多态
object Extends2{
	def main(args: Array[String]): Unit = {
		val b1:B1 = new B1
		val a1:A1 = b1
		println(b1.a) //20
		println(a1.a) //20 但在 java中输出为10 java中属性没有多态
	}
}
class A1{
	val a:Int = 10
}
class B1 extends A1{
	override val a : Int = 20
}

5、抽象属性和抽象方法

java中有抽象类,scala中也有抽象类

scala中的抽象类可以有哪些成员

  1. 普通类可以有的,抽象类都可以
  2. 抽象类可以有抽象方法和抽象字段(属性)
  3. 抽象类不能直接创建对象,只能创建他的子类对象
object  Abs1{
	def main(args[String]): Unit = {
		val b:B = new B
		b.foo()
	}
}
abstract class A(var a : Int){
	//属性只有声明,不初始化,这就是抽象字段
	var b : Int
	//方法只有声明,没有实现,就是抽象方法
	def foo() : Int 
}
class B extends A(20){
	override var b : Int = _
	override def foo() : Int = {
		println("foo....")
		10
	}
}

6、单例对象(伴生对象)

1、java实现单例

  • 饿汉式
  • 懒汉式

2、scala中单例

  • 使用object关键字声明出来的对象就是一个单例对象,独立对象
  • 任何的对象(object,也可以是new),只要提供了apply方法,都可以使用方法一样去调用对象,实际就是在调用apply方法
  • 如果在同一个scala文件中,一个object的名字和一个class的名字一样,则它们分别叫伴生对象,半身类
  • 编译成字节码后,伴生对象是静态方法,半生类是非静态(对象方法)
object Single1{
	def main(args[String]): Unit = {
		A() //等价于 A.apply()
	}
}
object A{ //伴生对象
	def foo() : Unit = println("foo...")
	def apply():Int = {
		println("apply")
		10
	}
}
class A{  //伴生类
	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值