Scala-day04-面向对象

一:包(package)

        1:命名规则

        只能包含数字、字母、下划线、小圆点,但不能用数字开头,也不能使用关键字

        2:管理风格

// 用嵌套风格定义包
package com{

  import com.atguigu.scala.Inner

  // 在外层包中定义单例对象        //外层调用内层需要导包
  object Outer{
    var out:String = "out"
    println(Inner.in)
  }
  package atguigu{
    package scala{
      // 内层包中定义单例对象
      object Inner{
        val in:String = "in"
        def main(args: Array[String]): Unit = {
          println(Outer.out)        // 内层能直接使用外层变量
          Outer.out = "outer"
          println(Outer.out)
        }
      }
    }
  }
}

二:包对象

        在Scala中可以为每个包定义一个同名的包对象,定义在包对象中的成员,作为其对应包下的class和object的共享变量,可以直接访问

        不同的文件

//不同的文件
//文件1
package object chapter04 {
  //定义当前包共享的属性和方法
  val commonValue = "aaa"

  def commmonValue(): Unit = {
    println(s"$commonValue")
  }
}

//文件2
package chapter04

object Test02 {
  def main(args: Array[String]): Unit = {
    commmonValue()
    println(commonValue)
  }
}

        同一个文件

// 同一个文件,要保证包对象和包声明在同一作用域中

package com{
    object Outer{
        val out:String = "out"
        def main(args:Array[String]):Unit = {
            println(name)
        }
    }
}

package object com{    
    val name:String = "com"
}

三:类和对象

        类:可以看出一个模板

        对象:表示具体的事物

        Java中一个.java有一个public类,Scala中没有public,一个.scala中可以写多个类

package chapter04

object Test03 {
  def main(args: Array[String]): Unit = {
    //创建一个对象
    val student = new Student()
    student.name //不能访问private属性
    println(student.age)
    println(student.sex)
    student.sex = "female"
    println(student.sex)
  }
}


//定义一个类,不加修饰符,默认public
class Student{
  //定义属性,不加修饰符,默认public
  private var name:String = "alice"
  var age:Int = _
  var sex:String = _
}

四:封装

        1:访问权限

1:Scala中的属性和方法默认都是public,但Scala中没有public

2:private为私有权限,只有在类的内部和伴生对象中可用

3:protect,同类、子类可以访问,同包无法访问

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

        2:案例

package chapter04

object Test04 {
  //创建对象
  val person:Person = new Person()
  println(person.age)
  //name也不能访问
  println(person.sex)
}

//定义一个子类
class Worker extends Person{
  // idCard无法访问
  override def printInfo(): Unit = {
    println("worker...")
    // println(idCard) 不能访问
    name = "bob"
    age = 25
    sex = "male"
    println(s"worker: $name $sex $age")
  }
}

        3:构造器格式

                辅助构造器,函数的名称this,可以有多个,编译器通过参数的个数及类型来区分

                辅助构造方法不能直接构建对象,必须直接或间接调用主构造方法

                构造器调用其他另外的构造器,要求被调用构造器必须提前声明

class 类名(形参列表){    //主构造器
    //    类体
    def this(形参列表){    //辅助构造器
        
    }

    def this(形参列表){    //辅助构造器可以有多个...
        
    }    
}

        4:案例

package chapter04

object Test05_Constructor {
  def main(args: Array[String]): Unit = {
    val student1 = new Student1
    student1.Student1()

    val student2 = new Student1("alice")

    val student3 = new Student1("`bob",25)
  }
}

//定义一个类
class Student1(){
  //定义属性
  var name:String = _
  var age:Int = _

  println("1.主构造方法被调用")

  //声明辅助构造方法
  def this(name:String){
    this()  //直接调用主构造器
    println("2.辅助构造方法一被调用")
    this.name = name
    println(s"name:$name age:$age")
  }

  def this(name:String,age:Int){
    this(name)
    println("3.辅助构造方法二被调用")
    this.age = age
    println(s"name:$name age:$age")
  }

  def Student1():Unit = {
    println("一般方法被调用")
  }
}

        5:构造器参数

                主构造器参数1:未用任何修饰符修饰,这个参数就是一个局部变量

                2:var修饰参数,作为类的成员属性使用,可以修改

                3:val修饰参数,作为类只读属性使用,不能修改

package chapter04

object Test06_ConstructorParams {
  def main(args: Array[String]): Unit = {
    val student2 = new Student2
    println(s"student2:name = ${student2.name},age = ${student2.age}")

    val student3 = new Student3("bob",20)
    println(s"student2:name = ${student3.name},age = ${student3.age}")

    val student4 = new Student4("cary",20)
    // println(s"student2:name = ${student4.name},age = ${student4.age}")  //获取不到,主构造器参数列表没有修饰符,不是属性值
    student4.printInfo()

    val student5 = new Student5("bob",20)
    println(s"student2:name = ${student5.name},age = ${student5.age}")
    
    // student5.age = 21  //  val 不可变   error
  }
}

//定义类
//无参构造器
class Student2{
  //单独定义属性
  var name:String = _
  var age:Int = _
}

//上面定义等价于
class Student3(var name:String,var age:Int)

//主构造器参数无修饰
class Student4(name:String,age:Int){
  def printInfo(): Unit ={
    println(s"student4 name = ${name} , age = ${age}")
  }
}

class Student5(val name:String,val age:Int)

class Student6(var name:String,var age:Int){
  var school:String = _
  def this(name:String,age:Int,school:String){
    this(name,age)
    this.school = school
  }
}



五:继承

        1:基本语法

class 子类名 extends 父类名{类体}

子类继承父类的属性和方法

Scala是单继承

        2:案例

package chapter04

object Test07_Inherit {
  def main(args: Array[String]): Unit = {
    val student1 = new Student7("alice",18)
    val student2 = new Student7("bob",20,"std001")
  }
}


//定义一个父类
class Person7(){
  var name:String = _
  var age:Int = _

  println("1.父类的主构造器调用")

  def this(name:String,age:Int){
    this()
    println("2.父类的辅助构造器被调用")
    this.name = name
    this.age = age
  }

  def printInfo():Unit = {
    println(s"Person:$name $age")
  }
}

//定义子类
class Student7(name:String,age:Int) extends Person7{
  var stdNo:String = _
  println("3.子类的主构造器调用")

  def this(name:String,age:Int,stdNo:String){
    this(name,age)
    println("4.子类的辅助构造器调用")
    this.stdNo = stdNo
  }
}

六:多态(子类的对象赋给父类的引用)

        1:Scala,方法和属性都动态绑定

class Person {
    val name: String = "person"
    def hello(): Unit = {
        println("hello person")
    }
}

class Teacher extends Person {
    override val name: String = "teacher"
    override def hello(): Unit = {
        println("hello teacher")
    }
}

object Test {
    def main(args: Arra y[String]): Unit = {
        val teacher: Teacher = new Teacher()
        println(teacher.name)
        teacher.hello()
        val teacher1: Person = new Teacher
        println(teacher1.name)
        teacher1.hello()
    }
}

//结果
teacher
hello teacher
teacher
hello teacher

        2:Java,方法动态绑定,但是属性并没有动态绑定

class Person {
    public String name = "person";
    public void hello() {
        System.out.println("hello person");
    }
}

class Teacher extends Person {
    public String name = "teacher";
    @Override
    public void hello() {
        System.out.println("hello tea cher");
    }
}

public class TestDynamic {
    public static void main(String[] args) {
        Teacher teacher = new Teacher();
        Person teacher1 = new Teacher();
        System.out.println(teacher.name);
        teacher.hello();
        System.out.println(teacher1.name);
        teacher1.hello();
    }
}

//结果
teacher
hello teacher
person
hello teacher

七:抽象类

        1:抽象属性和抽象方法

定义抽象类:abstract class Person(){} //通过abstract关键字标记抽象类

定义抽象属性:val | var name:String //一个属性没有初始化,就是抽象属性

定义抽象方法:def hello():String //只声明而没有实现的方法,就是抽象方法

        2:案例

package chapter05

object AbstractClass {
  def main(args: Array[String]): Unit = {
    
  }
}
//定义抽象类
abstract class Person9{
  //非抽象属性
  val name:String = "person"
  
  //抽象属性
  var age:Int
  
  //非抽象方法
  def eat():Unit={
    println("person eat")
  }
  
  //抽象方法
  def sleep():Unit
}

//定义具体的实现子类
class Student9 extends Person9{
  var age:Int = 18

  def sleep(): Unit = {
    println("student sleep")
  }

  //重写非抽象属性和方法
  override val name: String = "student"

  override def eat(): Unit = {
    println("student eat")
  }
}

        3:继承&重写

1:如果父类为抽象类,那么子类需要将抽象的属性和方法实现,否则子类也需声明为抽象类

2:重写非抽象方法需要用override修饰,重写抽象方法则可以不加override

3:子类中调用父类的方法使用super关键字

4:子类对抽象属性进行实现,父类抽象属性可以用var修饰

        子类对非抽象属性重写,父类非抽象属性只支持val类型,而不支持var

         4:匿名子类

package chapter05

object AnnoymousClass {
  def main(args: Array[String]): Unit = {
    val person:Person10 = new Person10 {
      override var name: String = "alice"

      override def eat(): Unit = println("person eat")
    }
    println(person.name)
    person.eat()
  }
}

//定义抽象类
abstract class Person10{
  var name:String

  def eat():Unit
}

八:单例对象,伴生对象

        1:背景

Java代码中的静态属性和方法,都是通过类名来调用的,没有做到面向对象

Scala将static关键字去掉,需要全局的属性和方法,引入了单例对象

        2:基本语法

object Person{
    val country:String="China"
}

        3:说明

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

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

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

        4:案例 

package chapter05

object Test11_Object {
  def main(args: Array[String]): Unit = {
    val student = new Student11("alice",18)
    student.printInfo()
  }
}

//定义类
class Student11(val name:String,val age:Int){
  def printInfo(): Unit ={
    println(s"student:name=${name},age=$age,school=${Student11.school}")
  }
}

//伴生对象
object Student11{
  val school:String = "atguigu"
}

九:特质

        1:背景

特质,trait,代替接口,多个类具有相同的特质时,就可以将这个特质独立出来,使用trait

trai既可以有抽象属性和方法, 也可以有具体的属性和方法,一个类可以混入多个特质

        2:声明

trait 特质名{
    trait   主体
}

         3:案例

package chapter05

object Test13_Trait {
  def main(args: Array[String]): Unit = {
    val student = new Studednt13
    student.sayHello()
    student.study()
    student.datting()
    student.play()
  }
}

//定义一个父类
class Person13{
  val name:String = "person"
  val age:Int = 18
  def sayHello():Unit={
    println("hello from:"+name)
  }
}

//定义一个特质
trait Young{
  //声明抽象和非抽象属性
  var age:Int
  val name:String = "young"

  //声明抽象和非抽象方法
  def play():Unit={
    println("young people is playing")
  }

  def datting():Unit
}

class Studednt13 extends Person13 with Young{
  //重写冲突的属性
  override val name: String = "student"

  //实现抽象方法
  def datting(): Unit = println(s"student $name is datting")

  //
  def study():Unit = println(s"student $name is studying")

  // 重写父类方法
  override def sayHello(): Unit = {
    super.sayHello()
    println(s"hello from:student $name")
  }
}

        4:基本语法

一个类具有某种特质,就意味着这个类满足了这个特质的所有要素,所以在使用时,也采用了extends关键字,如果有多个特质或存在父类,那么需要采用with关键字

没有父类:class 类名 extends 特质1 with 特质2 with 特质3...

有父类:class 类名 extends 父类 with 特质1 with 特质2 with 特质3...

        5:特质混入案例

package chapter05

object Test14_TraitMixin {
  def main(args: Array[String]): Unit = {
    val student = new Studednt14
    student.study()
    student.increase()

    student.play()
    student.increase()

    student.datting()
    student.increase()

    println("==============")
    //动态混入
    val studentWithTalent = new Studednt14 with Talent{
      override def dancing(): Unit = println("student is good at dancing")
      override def singing(): Unit = println("student is good at singing")
    }
    studentWithTalent.sayHello()
    studentWithTalent.play()
    studentWithTalent.study()
  }
}


//再定义一个特质
trait Knowledge{
  var amount:Int = 0
  def increase():Unit
}

trait Talent{
  def singing():Unit
  def dancing():Unit
}

class Studednt14 extends Person13 with Young with Knowledge {
  //重写冲突的属性
  override val name: String = "student"

  //实现抽象方法
  def datting(): Unit = println(s"student $name is datting")

  //
  def study():Unit = println(s"student $name is studying")

  // 重写父类方法
  override def sayHello(): Unit = {
    super.sayHello()
    println(s"hello from:student $name")
  }

  override def increase(): Unit = {
    amount += 1
    println(s"student $name knowledge increased: $amount")
  }
}

         6:特质叠加

就是一个类,继承有父类和其他特质。

然后假如说父类和特质有重复的属性的时候,需要重写一下即可。

假如说时父类和特质有重复的方法的时候,也需要重新,但这个重新会调用super的方法,这个super指的是,最后一个with关键字的内容,即最后面的内容

package chapter05

object Test15_TraitOverlying {
  def main(args: Array[String]): Unit = {
    val student = new Student15
    student.increase()
  }
}

//
//再定义一个特质
trait Knowledge15{
  var amount:Int = 0
  def increase():Unit = {
    println("knowledge increased")
  }
}

trait Talent15{
  def singing():Unit
  def dancing():Unit
  def increase():Unit = {
    println("talent increased")
  }
}

class Student15 extends Person13 with Talent15 with Knowledge15{
  override def dancing(): Unit = println("dancing")

  override def singing(): Unit = println("singing")

  override def increase(): Unit = {
    super.increase()
  }
}

         7:钻石叠加继承问题

package chapter05

object Test15_TraitOverlying {
  def main(args: Array[String]): Unit = {
    val student = new Student15
    student.increase()

    //钻石问题特质叠加
    val myFootBall = new MyFootBall
    println(myFootBall.describe())
  }
}

//定义球类特征
trait Ball{
  def describe():String = "ball"
}

//定义颜色特质
trait ColorBall extends Ball{
  var color:String = "red"

  override def describe(): String = color + "-" + super.describe()
}

//定义种类特征
trait CategoryBall extends Ball{
  var category:String = "foot"

  override def describe(): String = category + "-" + super.describe()
}

//定义一个自定义球类
class MyFootBall extends CategoryBall with ColorBall{
  override def describe(): String = "my ball is " + super.describe()
}


//再定义一个特质
trait Knowledge15{
  var amount:Int = 0
  def increase():Unit = {
    println("knowledge increased")
  }
}

trait Talent15{
  def singing():Unit
  def dancing():Unit
  def increase():Unit = {
    println("talent increased")
  }
}

class Student15 extends Person13 with Talent15 with Knowledge15{
  override def dancing(): Unit = println("dancing")

  override def singing(): Unit = println("singing")

  override def increase(): Unit = {
    super.increase()
  }
}

         8:抽象类和特质的区别

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

2:如果需要构造函数参数,使用抽象类,因为抽象类可以定义带参数的构造函数,特质不行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

总会有天明

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值