前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Scala学习二-面向对象

Scala学习二-面向对象

作者头像
路行的亚洲
发布2020-10-26 15:35:44
8520
发布2020-10-26 15:35:44
举报
文章被收录于专栏:后端技术学习后端技术学习

在Scala中创建类和对象

代码语言:javascript
复制
object OopDemo{
 //创建类
 class Monkey(){}
 //创建main方法
  def main(args: Array[String]): Unit = {
      //创建Monkey对象
      val m = new Monkey()
      //进行输出
      println(m)
  }  
}

省略条件

代码语言:javascript
复制
1.如果类是空的,没有成员变量,可以省略{ }
2.如果构造器的参数为空,可以省略( )

因此上面可以简写为:

代码语言:javascript
复制
object OopDemo{
    //创建类,没有成员变量,根据条件1省略{ }
    class Monkey
    //创建main方法
    def main(args: Array[String]): Unit = {
        //创建Monkey对象,由于是空参对象,因此根据条件2省略()
        val m = new Monkey
        //进行输出
        println(m)
    }
}

带成员变量类对象

代码语言:javascript
复制
object OopDemo{
    //创建monkey类
    class Monkey{
       //定义成员变量
        var name = ""
        var age = 0
    }
    //创建main方法,25的程序猿
    def main(args: Array[String]): Unit = {
        //创建Monekey对象
        //val m = new monkey()
        val m = new Monkey
        //设置属性值
        m.name = "程序员"
        m.age = 25
        //进行输出
        println(m.name+"----------"+m.age)
    }
}

使用下划线进行成员变量初始化

适用于var变量,对于val不适用,注意如果使用下划线进行初始化,此时必须提供数据类型,这样就可以进行自动推断赋初始值

代码语言:javascript
复制
object OopDemo{
  //创建Monkey类,带成员变量
    class Monkey{
        var name:String = _
        var age:Int = _
    }
    
   //创建main方法,25的程序猿
    def main(args:Array[String]): Unit = {
        //创建monkey对象,设置属性值
        val m = new Monkey
        m.name = "程序员"
        m.age = 25
        //进行输出
        println(m.name+"-------"+m.age)
    }
}

定义和访问成员方法

代码语言:javascript
复制
def 方法名(参数1:数据类型,参数2: 数据类型): [return type] = {
    //方法体
}

注:返回数据类型可以不写

代码语言:javascript
复制
object  OopDemo{
    //创建Monkey类
    class Monkey{
        //定义成员变量
        var name:String = _
        var age = 0
        
        //定义成员方法eatBanana,喜欢吃香蕉
        def eatBanana(msg: String) = {
            println(msg)
        }
    }
    
    //创建main方法,一个25的喜欢吃香蕉的程序猿
    def main(args: Array[String]): Unit = {
       //创建monkey对象
        val m = new Monkey
        m.name = "程序员"
        m.age = 25
        //进行输出
        println(m.name+"------------"+m.age)
        //调用成员方法eatBanana
        eatBanana("喜欢吃香蕉")
    }
}

访问权限修饰符

scala的权限修饰符:private,private[this],protected,默认四种,没有public修饰符

我们使用private修饰成员变量

代码语言:javascript
复制
object OopDemo{
  //创建monkey
  class Monkey{
      //定义成员变量,使用private
      private var name = ""
      private var age = 0
      
      //定义成员方法
      def getName() = name
      //设置姓名
      def setName(name: String) = this.name = name
      
      //获取年龄
      def getAge() = age
      //设置年龄
      def setAge(age: Int) = this.age = age
      
      //定义方法
      def eatBanana() = println("喜欢吃香蕉")
      }
  }
    
  def main(args: Array[String]): Unit = {
      //创建monkey对象
      val m = new Monkey
      m.setName("程序员")
      m.setAge(25)
      //进行输出
      println(m.getName() + "------" + m.getAge())
  }
}

主构造器

代码语言:javascript
复制
class 类名(var/val 参数名:类型 = 默认值, var/val 参数名: 类型 = 默认值){
    //构造代码块
}

如:设置构造器

代码语言:javascript
复制
object OopDemo{
    //创建monkey类,主构造器
    class Monkey(val name: String = "程序员", val age: Int = 25){
        println("调用了主构造器")
    }
    
    //创建main方法
    def main(args: Array[String]): Unit = {
        //创建空对象
        val m = new Monkey
        println(s"m: ${p.name}.....${p.age}")
        
        //创建对象,对应
        val m1 = new Monkey("程序员",25)
        println(s"m1: ${m1.name}.....${m1.age}}")
        
        //创建对象,仅传入年龄
        val m2 = new Monkey(age = 28)
        println("m2: ${m2.name}....${m2.age}")
    }
}

辅助构造器

辅助构造器的默认名字都是this,且不能修改,辅助构造器的第一行代码,必须要调用主构造器或者其他辅助构造器

代码语言:javascript
复制
def this(参数名: 类型,参数名: 类型){
  //第一行需要调用主构造器或者其他构造器
  //构造器代码  
}
代码语言:javascript
复制
object OopDemo{
    //定义构造函数
    class Monekey(var name: String, var hobbby: String){
       //定义辅助构造方法
        def this(arr: Arrray[String]){
            this(arr(0),arr(1))
        }
    }
   //创建main函数
    def main(args: Array[String]): Unit = {
       //创建对象
        var m = new Monkey(Array("程序员","喜欢吃香蕉"))
        //进行结果
        println(m.name+"--------"+m.hobbby)
    }
}

单例对象

代码语言:javascript
复制
object 单例对象名{ } //定义一个单例对象
代码语言:javascript
复制
object OopDemo{
 //创建单例对象
 object Monkey{
     //定义一个方法
     def monkeyLike() = monkeyHobby("monkey爱吃香蕉")
     }
    //创建main方法
    def main(args: Array[String]): Unit = {
        //调用单例对象的成员方法
        Monkey.monkeyLike()
    }
 }
}

定义程序主入口

scala和java一样,如果要运行一个程序,必须有一个main方法。在java中main方法是静态的,而在scala中没有静态方法,所以在scala中,main方法必须放在一个单例对象中。

main方法
代码语言:javascript
复制
def main(args:Array[String]):Unit = {
 //方法体
}
继承App特质

创建一个object,继承自App特质(Trait),然后将需要编写在main方法中的代码,写在object的构造方法体内

代码语言:javascript
复制
object 单例对象名 extends App{
   //方法体
}

在kafka中,我们可以看到程序的主入口是kafka.scala

代码语言:javascript
复制
//主入口
def main(args: Array[String]): Unit = {
    try {
      //获取配置信息服务端  
      val serverProps = getPropsFromArgs(args)
      val kafkaServerStartable = KafkaServerStartable.fromProps(serverProps)

      try {
        if (!OperatingSystem.IS_WINDOWS && !Java.isIbmJdk)
          //注册日志信号处理器
          new LoggingSignalHandler().register()
      } catch {
        case e: ReflectiveOperationException =>
          warn("Failed to register optional signal handler that logs a message when the process is terminated " +
            s"by a signal. Reason for registration failure is: $e", e)
      }

      // attach shutdown handler to catch terminating signals as well as normal termination
      //添加关闭钩子函数  
      Runtime.getRuntime().addShutdownHook(new Thread("kafka-shutdown-hook") {
        override def run(): Unit = kafkaServerStartable.shutdown()
      })

      //kafkaServer端启动 重要
      kafkaServerStartable.startup()
      //等待关闭,这里使用了countDownLatch同步并发容器  
      kafkaServerStartable.awaitShutdown()
    }
    catch {
      case e: Throwable =>
        fatal("Exiting Kafka due to fatal exception", e)
        Exit.exit(1)
    }
    //进行退出 终端
    Exit.exit(0)
  }
}

伴生对象

一个class和obect具有相同的名字,这个object称为伴生对象,这个class称为伴生类

注意:

代码语言:javascript
复制
伴生对象必须要和伴生类一样的名字
伴生对象和伴生类在同一个scala源文件中
伴生对象和伴生类可以相互访问private属性
代码语言:javascript
复制
object OopDemo{
  //定义类Monkey
  class Monkey{
     //定义monkey的方法eat()方法,猴子爱吃香蕉
      def eat()= println(s"猴子爱吃${eat.foodName}")
  }
    //定义伴生对象,用来保存食物香蕉,注意这个对象中的成员是静态变量
    object Monkey{
        private var foodName = "banana"
    }
    //创建main方法
    def main(args: Array[String]): Unit = {
        //创建Monkey读写
        var m = new Monkey
        //调用Monkey中的eat方法
        m.eat()
    }
}

private[this]访问权限

如果某个成员的权限设置为private[this],表示只能在当前类中访问。伴生对象也不可以访问

代码语言:javascript
复制
object OopDemo{
    //创建一个Monkey类,属性为name,这里需要去掉private[this],否者会报错
    class Monkey(private[this] var name: String)
    
    //定义Monkey类的伴生对象
    object Monkey{
        //定义monkeyName方法
        def monkeyName(m:Monkey) = println(m.name)
    }
    //创建main方法
    def main(args: Array[String]) = {
        //创建Monkey对象
        val m = new Monkey("程序员")
        //进行输出
        Monkey.monkeyName(m)
    }
}

apply方法

在Scala中,支持创建对象的时候,可以不写new的操作,要想实现不写new操作,就需要通道伴生对象的appky方法来实现

定义apply方法

代码语言:javascript
复制
object 伴生对象名{
    def apply(参数名:参数类型, 参数名: 参数类型...) =  new 类(...)
}

创建对象

代码语言:javascript
复制
val 对象名 = 伴生对象名(参数1,参数2....)
代码语言:javascript
复制
object OopDemo{
  //创建monkey类,属性名
    calss Monkey(var name: String = "",var age: Int = 0)
  //创建Moneky类的伴生对象
    object Monkey{
       //定义apply方法,创建对象Monkey对象的时候可以不写new
        def apply(name: String, age: Int) = new Monkey(name, age)
  }
  //创建main方法
    def main(args: Array[String]): Unit = {
        //创建Monkey对象,28的程序猿
        val m = Monkey("程序员",28)
        //进行输出
        println(m.name+"---------"+m.age)
    }
}

继承

代码语言:javascript
复制
class/object A类 extends B类 {
    ...
}
继承

Monkey分为程序猿和金丝猴

代码语言:javascript
复制
object OopDemo{
  //创建Monkey类
    class Monkey{
        var name = " "
        var age = 0
        
        def eat()=println("monkey爱吃香蕉")
    }
    
    //定义金丝猴
    class GoldenMonkey extends Monkey
    
    //定义程序猿
    class ProgramMonkey extends Monkey
    
    //创建main方法
    def main(args: Array[String]): Unit = {
       //创建金丝猴对象,喜欢吃香蕉的金丝猴
        val g = new GoldenMonkey
        g.name = "金丝猴"
        g.age = 2
        println(g.name + "----------" + g.age)
        g.ear()
        
        //创建程序猿,一个28爱吃香蕉的程序猿
        val p = new ProgramMonkey
        p.name = "程序猿"
        p.age = 28
        println(p.name + "----------" + p.age)
        p.eat()
    }
}
单对象继承

在Scala中,单例对象也可以继承类的

代码语言:javascript
复制
object OopDemo{
 //创建monkey类
  class Monkey{
      var name =" "
      
      def eat() = println("喜欢吃芒果")
  }  
  //定义单例对象programMonkey
    object ProgramMonkey extends Monkey
  
 //创建main方法,一个喜欢吃芒果的程序猿
    def main(args: Array[String]): Unit = {
       ProgramMonkey.name = "程序猿"
       println(ProgramMonkey.name)
       ProgramMonkey.eat()
    }
}
方法重写

子类中出现和父类一模一样的方法时, 称为方法重写. Scala代码中可以在子类中使用override来重写父类的成员,也可以使用super来引用父类的成员.可以使用override来重新一个val字段。

代码语言:javascript
复制
Object OopDemo{
  //定义父类Monkey
    class Monkey{
        var name = "猴子"
        val age = 2
        
        def eat() = println("吃香蕉")
    }
  
  //定义子类ProgramMonkey
    class ProgramMonkey extends Monkey{
        //使用override重写方法和变量
        override val age = 28
        override def eat() = {
            super.eat()
            println("同样喜欢吃芒果")
        }
    }
    
    //main方法,喜欢吃香蕉和芒果的程序猿
    def main(args: Array[String]): Unit = {
        //创建ProgramMonkey对象
        val p = new ProgramMonkey
        println(p.name + "--------" + p.age)
        p.eat()
    }
}

类型判断

有两种方式:

代码语言:javascript
复制
1.isInstanceOf:判断对象是否为指定类的对象
  asInstanceOf:将对象转换为指定类型
  
2.getClass/classOf:如果要求精确地判断出对象的类型就是指定的数据类型,那么就只能使用 getClass 和 classOf 来实现.
isInstanceOf/asInstanceOf
代码语言:javascript
复制
object OopDemo{
    //创建Monkey类
    class Monkey
  
    //创建一个ProgramMonkey
    class ProgramMonkey extends Monkey{
        def eat() = println("吃香蕉")
    }
    //main方法
    def main(args: Array[String]): Unit = {
        //通过多态创建programMonkey对象
        val p: Monkey = new ProgramMonkey
        //创建其是不是Monkey类型的对象,如果是,则将其转为Monkey类型的对象
        if(p.isInstanceOf[Monkey]){
        //调方法
        p.eat()
    }
  }
}

注意:isInstanceOf只能判断对象是否为指定类以及其子类的对象,而不能精确的判断出:对象就是指定类的对象。如果要求精确地判断出对象的类型就是指定的数据类型,那就只能使用getClass和classOf来实现

getClass和classOf
代码语言:javascript
复制
getClass可以精确获取对象的类型
classOf[类名]可以精确获取数据类型
使用==操作符可以直接比较类型
代码语言:javascript
复制
object OopDemo{
 //创建Monkey类
 class Monkey
 //创建一个ProgramMonkey类继承Monkey
  class ProgramMonkey extends Monkey
  
  def main(args: Array[String]): Unit = {
      //创建ProgramMonkey对象
      val p:ProgramMonkey = new ProgramMonkey
      //通过isInstanceOf关键字来判断是否是Monkey类型的对象 //true
      println(p.isInstanceOf[ProgramMonkey])
      //通过isInstanceOf关键字来判断是否是Monkey类型的对象 //false
      println(p.getClass == classOf[Monkey])
      //通过getClass,ClassOf判断其是否是ProgramMonkey
      println(p.getClass==classOf[ProgramMonkey]) //true
  }  
}

抽象类

代码语言:javascript
复制
//定义抽象类
abstract class 抽象类名{
    //定义抽象字段
    val/var 抽象字段名:类型
    //定义抽象方法
    def 方法名(参数:参数类型,参数: 参数类型...):返回类型
}
代码语言:javascript
复制
object OopDemo{
   //抽象类
    abstract class Monkey{
        val name: String
    }
    //定义ProgramMonkey继承Monkey,重新抽象字段
    class ProgramMonkey extends Monkey{
        override val name: String = "猴子"
    }
    //金丝猴类
    class GoldenMonkey extends Monkey{
        override val name: String = "金丝猴"
    }
    //程序猿
    class ProgramMonkey extends Monkey{
        override val 
    }
    
    //main方法
    def main(args: Array[String]): Unit = {
        //创建ProgramMonkey类的对象,输出
        val g = new GoldenMonkey
        println(g.name)
        //创建ProgramMonkey类的对象,进行输出
        val p = new ProgramMonkey
        println(p.name)
    }
}

匿名内部类

匿名内部类是继承了类的匿名的子类对象,它可以直接用来创建实例对象。

代码语言:javascript
复制
new 类名(){
   //重新类中所有的抽象内容
}

使用场景

代码语言:javascript
复制
1.(成员方法)仅调用一次的时候.
2.可以作为方法的参数进行传递.
代码语言:javascript
复制
object OopDemo{
    //创建Monkey类,里面有一个抽象方法:eat()
    abstract class Monkey{
        def eat()
    }
    //定义一个show()方法,该方法传入一个Monkey类型的对象
    def show(m:Monkey) = m.eat()
    
    //main方法
    new Monkey{
        override def eat(): Unit = {
            println("喜欢吃香蕉,当堆成员方法仅调用一次的时候")
        }.eat()
    
    
    //匿名内部类可以作为方法的参数进行传递
    val m = new Monkey{
        override def eat(): Unit = println("可以作为方法的实际参数进行传递")
    }
     show(m)  
   }
}

特质

代码语言:javascript
复制
1.特质可以提高代码的复用性
2.特质可以提高代码的扩展性和可维护性
3.类与特质之间是继承关系,只不过类与类之间只支持单继承,但是类与特质之间,既可以单继承,也可以多继承
4.Scala的特质中可以有普通字段, 抽象字段, 普通方法, 抽象方法.
代码语言:javascript
复制
trait 特质名称{
    //普通字段
    //抽象字段
    
    //普通方法
    //抽象方法
}

继承特质

代码语言:javascript
复制
class 类 extends 特质1 with 特质2{
    //重写抽象字段
    //重写抽象方法
}

注意:

代码语言:javascript
复制
1.scala中不管是类还是特质,继承关系用的都是extends关键字
2.如果要继承多个特质(trait),则特质名之间使用with关键字隔开
代码语言:javascript
复制
//trait入门之类继承单个特质
object OopDemo{
    //定义一个特质,抽象方法
    trait Logger{
        def log(msg:String)
    }
    //定义一个类,继承特质
    class ConsoleLogger extends Logger{
        override def log(msg: String): Unit = println(msg)
    }
    
    def main(args: Array[String]): Unit = {
        //调用类中的方法
        val cl = new ConsoleLogger
        c1.log("类继承单个特质")
    }
}

类继承多个trait

代码语言:javascript
复制
//案例: 类继承多个trait
object OopDemo {
  //1. 定义一个特质: MessageSender, 表示发送信息.
  trait MessageSender {
    def send(msg:String)
  }
  //2. 定义一个特质: MessageReceiver, 表示接收信息.
  trait MessageReceiver {
    def receive()
  }
  //3. 定义一个类MessageWorker, 继承两个特质.
  class MessageWorker extends MessageSender with MessageReceiver {
    override def send(msg: String): Unit = println("发送消息: " + msg)

    override def receive(): Unit = println("消息已收到, 我很好, 谢谢!...")
  }

  //main方法, 作为程序的主入口
  def main(args: Array[String]): Unit = {
    //4. 调用类中的方法
    val mw = new MessageWorker
    mw.send("Hello, 你好啊!")
    mw.receive()
  }
}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-10-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 后端技术学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 在Scala中创建类和对象
  • 带成员变量类对象
  • 使用下划线进行成员变量初始化
  • 定义和访问成员方法
  • 访问权限修饰符
  • 辅助构造器
  • 单例对象
  • 定义程序主入口
    • main方法
      • 继承App特质
      • 伴生对象
      • private[this]访问权限
      • apply方法
      • 继承
        • 继承
          • 单对象继承
            • 方法重写
            • 类型判断
              • isInstanceOf/asInstanceOf
                • getClass和classOf
                • 抽象类
                • 匿名内部类
                • 特质
                相关产品与服务
                容器服务
                腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档