一、面向对象
重要的两个概念
类:相同的事物组成的一个类或裙(抽象概念:描述一类相同的事物)
对象:一个类或群体里的单个实体
面向对象的四大特征
抽象,封装,继承,多态
构建实例对象的五种方法:
1,调用构造器(公开)
2,静态工厂方法(构造器私有)
3,反射
4,克隆(object.clone())
5,反序列化
在scala的类中,与类名相同的单例对象叫伴生对象,也就是如果我们在object Dog所在的文件内定义了一个class Dog,此时:
1,object Dog被称为class Dog的伴生对象
2, class Dog被称为object Dog的伴生类
3,类和伴生对象之间可以相互访问私有的方法和属性,private[this]修饰的除外
1. 定义类
- 定义类的时候,把伴生类和伴生对象放到一个文件中
- 如果一个其他类在当前文件中使用一次,可以定义在这个文件中
- 如果其他类被多次使用,最好定义到一个独立的文件中
//伴生类
class Student{
/**
* 1,在scala中定义的属性都需要初始化
* 2,使用val修饰的属性,具有getter方法不具有setter方法
* 3,var修饰的属性具有getter和setter方法
* 4,private修饰的变量表示私有,除了自己以外,任何组件不能访问
* 但是和当前这个类同名的object组件(对应的伴生对象)中可以访问
* private修饰的属性,除了自己和自己的伴生对象可以访问,其他都不能访问
* 5,private[this]修饰的属性,只有自己访问,伴生对象也不能访问
*
*/
val id = 9527
var name = "唐伯虎"
private var age = 18
private[this] var salary = 400000
println(age)//直接在类中就可以打印,Java中要在代码块中,这是因为scala中,由于构造方法和类名在一起,所以类体也是构造方法体,初始化构造方法时,自然会执行该代码
}
/**
* 如果要执行某个代码测试,就需要一个main方法组件,而且该方法必须在object中,不能放在class中,这是因为main方法相当于java中的main方法,是静态的,而scala的object相当于java中的静态类
* 在scala的一个代码文件中,可以同时定义多个类,而且这多个类可以都是public的那么其实如果没有使用任何修饰,那么这个类就是public的
* Java中多个类,则只有一个是public的
* class和object是互为伴生关系,class是伴生类,object是伴生对象
*/
//伴生方法
object Student{
def main(args: Array[String]): Unit = {
val student = new Student()
println(student.id)
}
}
获取类的信息
object ClassInfo {
def main(args: Array[String]): Unit = {
//Scala如果想要获取类的信息,需要采用特殊的方法:classOf[类型]
//classof能直接使用,因为scala.Predef伴生对象是默认导入到当前开发环境中
val userClass:Class[User] = classOf[User]
println(userClass.getInterfaces)
//可以使用type关键字给类起别名
type user2 = User
val user3 = new user2
val user: Object = new User
//判断类型
val bool: Boolean = user.isInstanceOf[user2]
//转换类型
if(bool){
val user1:User = user.asInstanceOf[User]
}
}
}
class User {
}
2. 定义构造器
定义无参构造器
/**
* 1, 在定义一个scala的类使,如果这个类名后面没跟()
* 就认为这个类有一个主构造器 类型() 但是()也可以省略
* scala中的主构造器类似于java中的无参构造器
* 2, 主构造器:直接写在类名后面的()就是
*
*/
class Student(){
val id = 9527
var name = "tbh"
println("hello scala")
}
object Student{
def main(args: Array[String]): Unit = {
val student = new Student()
println(student.id,student.name)
}
}
定义有参构造器
//1.如果有参构造中的参数使用var或val修饰,默认是public的,相当于定义了一个成员变量
//2.如果属性不使用var或val修饰,就相当于是private[this] val修饰的属性
class Student(val id:Int, var name:String, age:Int){
println("hello scala")
}
object Student{
def main(args: Array[String]): Unit = {
val student = new Student(9527,"thb",18)
println(student.id,student.name)
}
}
私有主构造器
/**
*构造器参数可以不带val或var
* 不带val或var的参数至少被一个方法使用,就会被提升为字段
* 在类名后面加private和private[this]就变成私有的,相当于禁用了主构造器
* 如果一个类的主构造器被private[this]修饰,即使是伴生对象也不能访问了
* 这个时候就需要定义辅助构造器,有以下几个要点
* 1,使用def定义
* 2,方法的名称必须是this
*
*/
class Student private(val id:Int, var name:String, age:Int){
def myAge = println(age)
}
object Student{
def main(args: Array[String]): Unit = {
val student = new Student(9527,"thb",18)
println(student.id,student.name)
println(student.myAge)//调用myAge只返回空值在够造对象时就已经使用了该方法,是不能使用student.age访问age的
}
}
辅助构造器
/**
* 在类名后面加private和private[this]就变成私有的,相当于禁用了主构造器
* 如果一个类的主构造器被private[this]修饰,即使是伴生对象也不能访问了
* 这个时候就需要定义辅助构造器,有以下几个要点
* 1,使用def定义
* 2,方法的名称必须是this
* 3,辅助构造器中的参数列表一般来说,都要包括主构造器中的参数列表
* 4,辅助构造器的{}中的第一句代码都要以其它的构造器(其他的辅助构造器或主构造器开头)
* 5,里面的参数不能有修饰符
*/
class Student private[this](val id:Int, var name:String){
def this(id:Int, name:String, age:Int) = {
//调用了主构造器
this(id,name)//必须以调用主构造器或其他构造器开头,前面不能有其他代码
}
def this(id:Int, name:String, age:Int, xx:Int) = {
//调用了辅助构造器
this(id,name,age)//必须以调用主构造器或其他构造器开头,前面不能有其他代码
}
}
object Student{
def main(args: Array[String]): Unit = {
val student = new Student(9527,"thb",18)
println(student.id)
}
}
object ParentConstructor {
def main(args: Array[String]): Unit = {
val b: A = new B("zhangsan",20,"Beijing") // 一次打印 A的主构造的方法 B的主构造方法 B的辅助构造方法
}
}
class A() {
println("A的主构造的方法")
}
class B(b: String) extends A {
println("B的主构造方法")
def this(name: String,age:Int,address:String) {
this(address) // 辅助构造方法必须在第一行引用 主构造方法或辅助构造方法
println("B的辅助构造方法")
}
}
//如果父类主构造方法有参数,那么构建对象时必须显式的传递参数
//可以在继承的父类后面增加小括号,传递参数,等同于调用父类构造方法
class C() extends B("d"){
}
总结:
a. 带参构造器参数有4种类型
1,由var或val修饰,自动成为成员属性
2,没有var或val修饰,相当于private[this] val修饰
3,由private var/val修饰
4,由private[this] val 修饰
b. 主构造方法
1,与类名交互在一起
2,主构造器运行,类名后面大括号里面的代码都会运行
c. 辅助构造器
1,名字必须是this
2,必须以调用柱构造器或其他辅助构造器方法开始
3,里面的属性不能写修饰符
3. 类的方法及属性
// 类的方法,所谓的方法,其实就是类中声明的函数,所以声明方法和函数是一样的,调用上有区别
object Class_Method {
def main(args: Array[String]): Unit = {
val aaa = new BBB()
}
}
// 类可以声明为抽象的
abstract class AAA {
val i = 10
var age = "xxxx"
var name: String = _
//scala中属性也可以重写,因为属性可以抽象
//属性只声明,而没有初始化,那么就是抽象属性(scala中的属性必须显性初始化)
//抽象属性在编译为class文件时,不产生属性,但是产生一个getter方法
var sex: String
//声明抽象方法,方法只有声明没有实现,不需要abstract关键字
def test()
}
class BBB extends AAA {
// IDEA中重写方法的快捷键:ctrl+o(override) 实现方法快捷键:ctrl+i(implement)
//scala中如果子类重写父类的方法或属性(不是抽象的),必须要加关键字override
//实现抽象方法或属性override关键字可加可不加
override val i = 20
//scala中不可以重写var修饰的属性
override var age ="YYYY"
override var sex: String = _
override def test(): Unit = {
println("hello world")
}
}