Scala语言基础(四)面向对象(一)定义类、定义构造器

一、面向对象

重要的两个概念
类:相同的事物组成的一个类或裙(抽象概念:描述一类相同的事物)
对象:一个类或群体里的单个实体
面向对象的四大特征
抽象,封装,继承,多态
构建实例对象的五种方法:
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. 定义类

  1. 定义类的时候,把伴生类和伴生对象放到一个文件中
  2. 如果一个其他类在当前文件中使用一次,可以定义在这个文件中
  3. 如果其他类被多次使用,最好定义到一个独立的文件中
//伴生类
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")
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值