Scala 面向对象【中】

news/2024/11/23 20:59:40/

Scala 面向对象(中)

1、继承和多态

        用法和Java基本一致。

基本语法

        class 子类名 extends 父类名称 {}

案例演示

object Test07_Inherit {def main(args: Array[String]): Unit = {val student = new Student1("GG Bond",18)student.printInfo()}}//定义一个父类
class Person1(){var name: String = _var age: Int = _println("1. 父类主构造器调用")def this(name: String,age: Int){this()println("2.父类的辅助构造器被调用")this.name = namethis.age = age}def printInfo(): Unit = {println(s"${name} ${age}")}
}
//继承父类可以指定调用父类的构造器(需要给继承的父类传入参数,使用父类的主构造器还是辅助构造器取决于传入的参数是什么) 也可以不调用(直接extends Person1)
class Student1(name: String,age: Int) extends Person1(name,age){var school: String = _println("3. 子类的主构造器被调用")def this(name: String,age: Int,school: String){this(name,age)  //调用主构造方法this.school = schoolprintln("4. 子类的辅助构造器被调用")}//重写父类的方法override def printInfo(): Unit = {println(s"${name} ${age} ${school}")}
}

2、多态

2.1、动态绑定

Java中,只有方法的动态绑定的,但在Scala中,方法和属性都是动态绑定的。

Java:

public class Test {public static void main(String[] args) {Worker worker = new Worker();System.out.println(worker.name);worker.hello();System.out.println("============");//多态Person person = new Worker();System.out.println(person.name);person.hello();}}class Person{String name = "person";public void hello(){System.out.println("hello person");}
}class Worker extends Person{String name = "worker";public void hello(){System.out.println("hello worker");}
}

输出结果

worker
hello worker
============
person
hello worker

Scala:

Scala在重写父类的属性和方法时,需要再属性名和方法名之前使用 “override” 关键字。

package chapter05object Test08_DynamicBind {def main(args: Array[String]): Unit = {val student:Student8 = new Student8println(student.name)student.hello()println("=============")//多态val person:Person8 = new Student8println(person.name)person.hello()}}class Person8{val name = "person"def hello(): Unit = {println("hello person")}
}class Student8 extends Person8 {override val name = "student"override def hello(): Unit = {println("hello student")}
}

运行结果 

student
hello student
=============
student
hello student

可以看到,Scala通过父类创建子类对象后,在调用对象的方法时,会动态绑定当前的对象的属性和方法。

3、抽象类

3.1、抽象属性和方法

Scala中定义变量和方法时一般必须要求赋初始值,但是在抽象类中可以不遵守。

  • 在Scala中,只要一个类中有抽象方法和抽象属性,该类必须是抽象类。
  • 在Scala中,一个抽象类的属性和方法可以是已实现的。
  • 定义抽象类abstract class Person{} //通过 abstract 关键字标记抽象类
  • 定义抽象属性val|var name:String //一个属性没有初始化,就是抽象属性
  • 定义抽象方法def hello():String //只声明而没有实现的方法,就是抽象方法

3.2、抽象类的继承与重写

  1. 如果父类为抽象类,那么子类需要将抽象的属性和方法实现,否则子类也需声明为抽象类
  2. 重写非抽象方法需要用 override 修饰,重写抽象方法则可以不加 override
  3. 子类中调用父类的方法使用 super 关键字
  4. 子类对抽象属性进行实现,父类抽象属性可以用 var/val 修饰;
  5. 子类可以直接对一个被 var 修饰的变量进行赋值来实现重写,不需要使用 override 关键字,所以对于非抽象属性,不建议用 var 修饰。
abstract class Person9{//抽象属性val name: String//非抽象属性val age: Int = 18 //被val 修饰 子类需要重写var school = "山西农业大学" //被var修饰 子类不需要重写//抽象方法def hello():Unit//非抽象方法def eat(): Unit = {println("person eat")}}class Student9 extends Person9{//实现抽象属性val name: String = "李元芳"//实现抽象方法def hello(): Unit = {println("hello")}//重写非抽象属性override val age = 10school = "北京中医药大学"  //父类中被 var 修饰的非抽象变量可以直接重新赋值 不需要重写 所以不建议非抽象属性用 var 修饰//重写非抽象方法override def eat(): Unit = {super.eat()println("student eat")}}

4、匿名子类

匿名子类,也就是说不需要继承抽象父类,直接在定义对象的时候重写抽象属性和方法。

object Test {def main(args: Array[String]): Unit = {val person:Person10 = new Person10 {override var name: String = "GG Bond"override def hello(): Unit = {println("hello gays")}println(person.name)person.hello()}}}//定义抽象类
abstract class Person10{//定义抽象属性和方法var name: Stringdef hello(): Unit}

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

        Scala语言是 完全面向对象 的语言,所以并没有静态的操作(即在 Scala 中没有静态的概念)。但是为了能够和Java 语言交互(因为 Java 中有静态概念),就产生了一种特殊的对象来 模拟类对象, 该对象为 单例对象 。若单例对象名与类名一致,则称该单例对象这个类的 生对象 ,这个类的所有“静态”内容都可以 放置在它的伴生对象 中声明。

说明

  • 单例对象采用 object 关键字声明
  • 单例对象对应的类称之为伴生类,伴生对象的名称应该和伴生类名一致。
  • 单例对象中的属性和方法都可以通过伴生对象名(类名)直接调用访问。
  • 伴生类和伴生对象必须名字相同且在一个文件中
object Test {def main(args: Array[String]): Unit = {val bob = new Student11("bob", 18)bob.printInfo()}}//定义伴生类
class Student11(val name: String,val age: Int){def printInfo(): Unit = {println(s"${name} ${age} ${Student11.school}")}}
//定义伴生对象
object Student11{val school: String = "北京中医药大学"}

5.1、主构造器私有化

        有些时候我们不希望直接通过主构造器来创建对象实例,而是通过工厂方法来创建对象,在Scala中,我们可以借助伴生对象和伴生类可互相调用的特点来实现:

我们需要在伴生类的主构造器参数前使用 private 关键字进行修饰

object Test {def main(args: Array[String]): Unit = {
//    val bob = new Student11("bob", 18)
//    bob.printInfo()val bob = Student11.newStudent("bob", 18)bob.printInfo()}}//定义伴生类
class Student11 private (val name: String,val age: Int){def printInfo(): Unit = {println(s"${name} ${age} ${Student11.school}")}}
//定义伴生对象
object Student11{val school: String = "北京中医药大学"//定义一个类的对象实例的创建方法(工厂方法)def newStudent(name: String,age: Int): Student11 = {new Student11(name,age)}}

5.2、apply方法

使用 apply方法来实现工厂模式,可直接使用类名来创建对象,不需要显式地使用apply方法。

object Test {def main(args: Array[String]): Unit = {val alice = Student11.apply("alice",10)val tom = Student11("alice",10) //scala 调用apply方法可以省去方法名 简化代码alice.printInfo()tom.printInfo()}}//定义伴生类
class Student11 private (val name: String,val age: Int){def printInfo(): Unit = {println(s"${name} ${age} ${Student11.school}")}}
//定义伴生对象
object Student11{val school: String = "北京中医药大学"def apply(name: String,age: Int): Student11 = {new Student11(name,age)}}

5.3、单例设计模式

        单例设计模式,始终只有一个对象,即使我们在创建对象的时候,赋予不同的属性,但是返回的结果都只会是第一个对象的实例。

object Test12_Singleton {def main(args: Array[String]): Unit = {val student2 = Student12.getInstance("bob",20)student2.printInfo()    //bob 20 北京中医药大学val student1 = Student12.getInstance("alice",18)student1.printInfo()    //bob 20 北京中医药大学//输出相同的对象引用println(student1)    println(student2)}}
//定义伴生类
class Student12 private (val name: String,val age: Int){def printInfo(): Unit = {println(s"${name} ${age} ${Student12.school}")}}//饿汉式
//object Student12{
//  val school = "北京中医药大学"
//
//  private val student: Student12 = new Student12("alice",18)
//
//  def getInstance(): Student12 = student
//}//懒汉式
object Student12{val school = "北京中医药大学"private var student:  Student12 = _def getInstance(name: String,age: Int): Student12 = {if (student == null){//没有对象实例的话就创建一个student = new Student12(name,age)}student}
}

使用伴生对象可以很轻松地实现各种设计模式。


http://www.ppmy.cn/news/583711.html

相关文章

Qt官方示例:Fridge Magnets Example(冰箱贴)

冰箱贴类&#xff1a; #include "draglabel.h" #include <QtWidgets>DragLabel::DragLabel(const QString &text, QWidget *parent): QLabel(parent) {QFontMetrics metric(font());QSize size metric.size(Qt::TextSingleLine, text);QImage image(size…

2.3 案例3 加点料-增加一张图片

本案例对应的源代码目录&#xff1a;src/chapter02/ks02_03。程序运行效果见图2-21。 图2-21 案例3运行效果 既然要进行界面编程&#xff0c;自然离不开图片。如果认为在按钮上使用文字太枯燥了&#xff0c;那么使用图标是不是会更好呢&#xff1f;本节讨论一下如何在Qt项目中…

微信缓存dat怎么转图片_PC微信dat如何转图片?方式方法

微信dat转码软件使用操作说明在线解码,各位同学下载软件后&#xff0c;如何操作?如何找到dat文件?如何使用?又有哪些注意事项呢?这里会为大家一一道来。问题1 &#xff1a;如果下载失败怎么办?请先检查网络&#xff0c;软件并没有放在我的网站上&#xff0c;而是放在大厂七…

html5无法处理像素点导致图片花了,教你使用Canvas处理图片的方法

Canvas&#xff0c;中文译为“画布”&#xff0c;HTML5中新增了元素&#xff0c;可以结合JavaScript动态地在画布中绘制图形。 今天&#xff0c;我们不讲Canvas的图形绘制&#xff0c;而是讲如何对图片进行处理。 大概流程非常简单&#xff0c;主要分为以下三个步骤&#xff1a…

计算机教室英语手抄报图片,英语手抄报图片四年级

英语手抄报图片四年级 四年级的小朋友们&#xff0c;下面是有关四年级上册英语单词表图片手抄报内容知识&#xff0c;欢迎大家阅读与了解。 小学四年级上册英语单词表&#xff1a;Unit 1 My Classroom window 窗户  board 写字板  light 灯;管灯  picture 画;图画 door 门…

Java大象进冰箱线程_把大象装进冰箱:HTTP传输大文件的方法

上次我们谈到了HTTP报文里的div&#xff0c;知道了HTTP可以传输很多种类的数据&#xff0c;不仅是文本&#xff0c;也能传输图片&#xff0c;音频和视频。 早期互联网上传输的基本上都是只有几k大小的文本和小图片&#xff0c;现在的情况则大有不同。网页里包含的信息实在太多了…

微信小程序上传图片到html,微信小程序-上传图片

在做小冰箱这个项目时&#xff0c;对物品的图片需要有一个上传功能。今天在这里讲一下这个功能是如何实现的。 首先讲述一下这个功能的完整描述&#xff1a;有一个上传图片的按钮&#xff0c;点击按钮&#xff0c;弹出操作菜单&#xff1a;从手机相册选择&#xff0c;拍照。点击…

java html转图片格式_java把html转成图片的方法

代码 1.1 html模版 static String HtmlTemplateStr = " "body {background-color: yellow}"+ "h1 {background-color: #00ff00}"+ "h2 {background-color: transparent}"+ "p {background-color: rgb(250,0,255)}"+ "p.no2 …