一、类的基本操作

1、类的创建与对象的构造

定义scala中的类使用关键字class

  • 1、定义scala中的任意一种结构,都不可以使用public关键字修饰,因为scala中没有public关键字不加任何访问权限修饰符就相当于java中的public
  • 2、类中可以定义成员信息——成员变量,成员方法
  • 3、创建类的实例–对象。在scala中和java中是一样,都使用关键字new来构建类的实例
?:
object ClassOps {def main(args: Array[String]) {val p:Person = new Person()p.name = "zhnagsan"p.age = 18p.show()}
}
class Person{var name : String = _var age : Int = _def show():Unit={println(s"name:${name}\tage:${age}")}
}

2、成员变量的封装(getter&setter)

scala没法直接为成员变量提供getter和setter方法,只能自己编写

  • scala做了一种尝试,通过注解(@BeanProperty)的方式来给成员变量提供getter和setter,前提是该getter或者setter不能被private修饰,此时数据的安全性无法得到保证
  • Java中的getter和setter的的使用其实javabean中的规范,javabean的主要作用是什么?是封装和传递数据,而在scala中亦是如此
?:
object ClassOps {def main(args: Array[String]) {val p:Person = new Person()p.setName("zhangsan")p.setAge(18)p.show()}
}class Person{private var name : String = _private var age : Int = _def setName(n:String) = name = ndef getName = namedef setAge(a:Int) = age = adef getAge = agedef show():Unit={println(s"name:${name}\tage:${age}")}
}

3、scala类的构造器

3.1构造器

按照java中的知识,val stu = new Student是使用Student类的无参构造器创建对象的,在一个类中,如果局部变量和成员变量名发生冲突,便通过给成员变量加this关键字进行区分

3.2如何定义构造器

scala的构造,分为主构造器和辅助构造器,主构造器的定义和类的定义交织在一起,那么如何去定义一个主构造器呢?
class Xxx(参数列表) { }

类名后面的内容就是主构造器,如果参数列表为空的话,()可以省略;主构造器的函数体,就是类体的内容,所以如果我们使用主构造器创建对象
scala的类有且仅有一个主构造器,要想提供更加丰富的构造器,就需要使用辅助构造器
def this(参数列表)
scala中的辅助构造器,在函数体的第一行,必须以调用其它辅助构造器或者主构造器开始,也就是说要使用this(参数列表)去调用其它构造器,但是归根到底,一个辅助构造器最终还是要从主构造器的调用开始!

3.3scala和java的构造器的区别

  • java的构造器没有主构造器和辅助构造器之分,但是有默认的无参构造器和有参构造器之分
  • scala中默认的构造器就是类名后面的构造器,被称之为主构造器,同时还拥有辅助构造器
  • java的构造器名称和类名一致,而scala中的构造器名称就是this,其余和java一模一样
?:
object _02CaseClass {def main(args: Array[String]) {val stu = new Studentstu.show()println("------------------------------")}
}class Student(n:String,a:Int){private var name : String = _private var age : Int = _def Student(name:String,age:Int) : Unit={this.name=namethis.age=age}//辅助构造器def this(){this("lisi",16)println("----辅助构造器----")}def show():Unit={println(s"name:${n}\tage:${a}")}println("外围!!!!")
}

4、case class模拟javabean

在scala中一般不用这些普通的class类进行封装数据、传递数据,那用什么呢?
答案是使用case class样例类,其作用就相当于java bean
case class的定义非常简单,在class关键字的前面加上另外一个关键字case即可
样例类的定义必须要有一个参数列表---->构造器,
case class的应用是非常广泛的,但凡数据的传递,一般都用case class

?:
object _02CaseClass {def main(args: Array[String]) {//样例类testval category = Category(13,"平底锅")println(category.id)println(category.name)}//样例类的声明
case class Category(id:Int,name:String)

5、嵌套类

scala中称之为嵌套类,在java中称之为内部类
java中的成员内部类实例

?:
public class InnerClassOps {public static void main(String[] args) {Outer.Inner oi = new Outer().new Inner();oi.show();}
}
class Outer {class Inner {public void show() {System.out.println("inner show");}}
}

思考一个问题~那就是为什么要有内部类呢?

从业务逻辑上理解,定义复杂是否在外部类内部定义更加合理,这样便有了内部类,比如,定义一个Person类,Person类有心脏Heart,Heart优势一个复杂的抽象事物,显然应该把Heart定义在Person内部更加的准确与合理。

那么scala的内部类如何定义呢?

?:
object _03InnerOps {def main(args: Array[String]) {val outer = new Outerval inner = new outer.Innerinner.show()}
}class Outer{ o =>var x =5class  Inner{ i =>var x = 6def show():Unit={var x = 7println("Inner : x="+x)println("Inner : x="+this.x)println("Inner : x="+Outer.this.x)println("Inner : x="+o.x)        //简写方式println("Inner : x="+i.x)        //简写方式}}
}

6、对象object

scala并没有像java中的静态方法,所以按照java中的观点来看,主函数是没有办法被执行public static void main(xxx)
​scala为了来模拟java中的static这个关键字,设计出了object这一结构,它是和class平级。
​在object定义的方法我们可以理解为函数,class中的行为称之为方法,而且在object中定义的变量和函数都是可以当做java中的静态来进行调用。

?:
object _04ObjectOps {def main(args: Array[String]) {println(Tool.add(10,13))}
}object Tool{val x = 5def add(a:Int,b:Int) = a+b
}

scala中的单例

?:
object _05SingletonOps {def main(args: Array[String]): Unit = {val s1 = Singletonval s2 = Singletonprintln("s2.x=" + s2.x)//1s1.x = 5println("s1 == s2? " + (s1 == s2))//true 单例println("s2.x=" + s2.x)//5}
}
object Singleton {var x = 1
}

7、伴生对象和伴生类

为什么要有伴生对象?
​ 我们都知道,在scala中是没有静态这个概念,而在java中一个类是既可以有非静态的成员,也可以有静态成员,表达非常丰富。scala由于没有静态的概念,类只能拥有非静态成员。所以scala为了弥补这个缺憾,定义了一个和该类同名的object结构,而且该object结构必须要和该类在同一个.scala源文件中被定义
这样我们就可以让该类拥有了静态和非静态的成员。
把这个和类同名的object称之为该类的伴生对象,反过来,该类称之为该object的伴生类。

?:
object _06CompanionOps {def main(args: Array[String]) {val worker = new Worker("laowang",34)worker.showprintln("------------------")val w1 = Worker()println("静态属性:" + Worker.x)w1.show}
}class Worker{private var name:String = _private var age:Int = _def this(name:String,age:Int){this()this.name = namethis.age = age}def show: Unit ={println(s"name:${name}\tage:${age}")}
}object Worker{var x = 123//apply方法必须要重写def apply():Worker = new Worker()}

8、没有main函数如何执行scala程序

继承trait的APP就可以~

?:
object _07AppOps extends App {/*def main(args: Array[String]): Unit = {println("xxxxxx")}*/println(args.mkString("[", ",", "]"))println("yyyyyyyyyyyy")
}

二、继承体系

1、扩展类和重写方法(extends/override)

在scala中实现继承或者扩展使用的关键字和java的继承是一模一样,那就是extends关键字!
在scala中使用extends关键字有以下几个注意点:

  • 1、子类可以拥有父类的非私有的成员(成员变量和成员方法)
  • 2、子类可以扩展或复写父类的方法,但是在重写的时候,必须要添加override关键字(除非该方法是抽象方法)
  • 3、无法被子类继承的成员——private
  • 如果private关键字不加如何限制,就和java中的private作用是相同的,但是在scala中可以更加精准的去控制这个权限
  • private[可以被访问的包package] 这就意味着,该成员可以在包package,及其子包下面被访问
    private[this] 等效于 private,表示只能在前类中被访问
    注意:static scala中没有final
  • 4、子类要想使用父类的某些行为,可以使用super关键字来调用,和java中一致
?:
object _01ExtendsOps {def main(args: Array[String]) {val keji= new Keiji()keji.eat()keji.bark()}
}class Dog{private val id:String = "哺乳类动物"var eyes:Int =2var name:String = _def eat():Unit={println("吃方法")}def bark() : Unit = {println("叫方法")}
}class Keiji extends Dog{override def eat() : Unit={super.eat()println("柯基吃饭")}
}

2、类型检查和转换(isInstanceOf/asInstanceOf/match)

多态定义:一种事物有多重状态的表现,是继承体系中非常重要的概念。
多态反映到编程语言中的体现就是:父类引用指向子类对象。这个在java中是很明显的,但是在scala不明显,因为一般在定义变量的时候,可以不添加类型,直接做类型推断,所以要想很直接的体现出,就应该像java定义那样

 ?:val obj:Fu = new Zi() --->    父类引用指向子类对象 val obj = new Zi()

​ 同时在进行多态操作中,一般都会涉及到类型转化,scala中也有类似java中的类型检查和类型转化,不同之处在于具体操作方式略有差异,进行类型检查是:引用.isInstanceOf[类型],进行类型转化使用引用.asInstanceOf[类型]

?:
class Person {     //定义一个人的类var name:String = _var age:Int = _def this(name:String, age:Int) {  //有参构造器this()this.name = namethis.age = age}override def equals(obj: scala.Any): Boolean = {if(!obj.isInstanceOf[Person]) {   //判断如果obj不是Person的子类就返回falsereturn false}val that = obj.asInstanceOf[Person]  //将obj转换成Person类型//判断如果成员变量的name和局部变量的name相等说明类型转换成功if(this.name.equals(that.name) && this.age == that.age) {return true}return false}
}

但是,scala是一个非常简约的编程语言,又为大家提供了一个类型检查和转化的简化的操作方式——模式匹配,和java中switch case很像,但是要比java中的switch case强大的多。

?:
private def method3 = {val dh: Dog = new Keijidh.eat()if (dh.isInstanceOf[Keiji]) {//会避免出现ClassCastExceptionval gg = dh.asInstanceOf[Keiji]gg.keepDoor()}println("-----------------------")//使用模式匹配的操作方式 和switch case很像dh match {case gg:Keiji => {gg.keepDoor()}case p:Person => {p.name}//还有默认的操作case _ => {println("没办法匹配")}}
}

3、受保护字段和方法

所谓受保护的字段或者方法,就是被protected修饰的属性(field)或者方法(method)。
被protected修饰的本类及其子类方法有什么特点?
被protected[this]修饰了成员,便无法在实例(包括本类对象和子类对象)中被调用,只能在定义中被调用

?:
class Staff {var name:String = _var age:Int = _protected[this] var salary:Float = 2120def doWork(): Unit = {println(this.name + " is working sth.")}}class Programmer extends Staff {name = "leibusi"age = 52salary = 1000000000override def doWork(): Unit = {println(this.name + " 监督下属干活")}def makeFields(staff: Staff): Unit = {println(this.name + "准备要和" + staff.name + "建立革命友谊")println(staff.name + "的薪资是:" + staff.salary)}}

上述代码出现如下异常(大家可以体会一下~):

4、超类的构造

前面讲构造器的时候说到过:类有一个主构器和任意数量的辅助构造器,而每个辅助构造器都必须以对先前定义的辅助构造器或主构造器的调用开始。

子类的辅助构造器最终都会调用主构造器,只有主构造器可以调用超类的构造器,辅助构造器永远都不可能直接调用超类的构造器。

这个跟java还是有点区别的,java就可以直接使用super(…)来调用超类构造器,下来通过实例来看吧~

?:
object _05SuperClassOps {def main(args: Array[String]) {val zi = new Zi()zi.show()}
}class Fu {println("-----Fu---main-constructor---")var name:String = _var age:Int = _def this(name:String, age:Int) {this()this.name = namethis.age = ageprintln("-----Fu---assist-constructor(name:String, age:Int)---")}
}class Zi(name:String, age:Int, gender:Int) extends Fu(name, age) {println("-----Zi---main-constructor(gender:Int)---")def this() {//辅助构造器this("zhangsan", 14, 1)println("-----Zi---assist-constructor()---")}def show(): Unit = {println(s"name:${name}, age: $age, gender:$gender")}
}

代码运行效果(顺便可以捋一下构造器的调用):


总结:

scala在加载子类构造器的同时去加载父类构造器,其道理和java中是一致的,不同点在于scala只有主构造器才可以直接调用父类的构造器(主构造器和辅助构造器),辅助构造器是无法直接调用父类的构造器,因为在辅助构造器的第一句话必须用this去调用其他辅助构造器或者主构造器,所以辅助构造器只能通过主构造器来间接的调用父类的构造器。

5、匿名子类

匿名子类的概念: 没有名字的类就叫做匿名子类,new Person() {} —>这就是一个没有名字的类 —>是一个运行时的概念。

匿名子类最常见的作用是在某个操作仅仅出现一次的时候被使用,在方法的参数上面多出现匿名子类,在java中出现最多的匿名类或者匿名子类,就是接口或者抽象类。

?:
object NimingZilei {def main(args: Array[String]) {val worker = new Worker("zhangsan", 18)val police = new Worker("zhang sir", 28){//匿名子类override def work(): Unit = {super.work()println(name+"辛苦了")}def catchThief(): Unit = {println(name+"抓贼")}}police.catchThief()worker.makeFriend(police)}
}class Worker {var name:String = _var age:Int = _def this(name:String, age:Int) {this()this.name = namethis.age = age}def makeFriend(worker: Worker): Unit = {println(this.name + "和 " + worker.name + "成为了工友")worker.work()}def work(): Unit = {println("劳心者治人,劳力者治于人")}
}

运行效果:

6、抽象类和抽象字段(abstract)

抽象概念: 编程语言中的抽象,就是只给出了定义,并没有给出实现。只能交由具体的实现者来完成,为了表示抽象和非抽象(具像,具体),在java或者scala中使用关键字abstract来进行标识。
需要指出的是,在java中只有抽象方法,没有抽象字段,但是在scala既有抽象方法,又有抽象字段。
scala抽象类和抽象字段特点:

  1. scala既有抽象方法,又有抽象字段
  2. 抽象方法和抽象字段,不用abstract进行修饰,只有类采用abstract进行修饰
  3. 所谓抽象字段,只有在抽象类中才可以存在,也就是没有进行初始化的值
  4. 子类去覆盖父类抽象的时候,可以省略掉override关键字
?:
object _06AbstractOps {def main(args: Array[String]) {val china = new Chinese()china.eat()}
}abstract class Human{var name:Stringvar birthday:String = _def eat()def sleep():Unit={println("中午睡觉~")}
}class Chinese extends Human{override def eat(): Unit = {println(name+"用筷子吃饭")}override var name: String = "炎黄子孙"
}

7、trait特质(“接口”)

trait特质是一个和class、object同一level的结构。
trait和java中的接口有点像,但不完全一样,java中的interface中的所有的方法都是抽象的,而trait既可以拥有抽象方法,也可以拥有非抽象方法,所以其实可以理解为抽象类。
​那么问题来了,已经有了一个抽象类,那为什么还要有trait特质呢?
​那是因为,如果只有抽象类的话,在继承体系中只能单继承和多层继承,无法多extends,所以需要一个新的结构来弥补,这个结构就是trait特质。

注意: java中实现一个interface使用关键字implement,实现多个interface时候,interface之间使用“,”分割,scala中扩展trait的时候,同样也是extends关键字,扩展多个trait的时候,trait之间使用with关键字连接。
如果trait中的所有的方法都是抽象的,那就是java中的interface。

?:
object TraitOps {def main(args: Array[String]): Unit = {val mp = new MainOperationmp.debug("----------高山流水忘乎于情----------")}
}//特质
trait Logger {def log(msg:String)
}trait ConsoleLogger extends Logger {override def log(msg: String): Unit = {println("ConsoleLogger> " + msg)}
}class FileLogger extends Logger {override def log(msg: String): Unit = {println("FileLogger> " + msg)}
}class DailyFileLogger extends Logger {override def log(msg: String): Unit = {println("DailyFileLogger> " + msg)}
}class MainOperation extends ConsoleLogger with Logger{def debug(msg:String): Unit = {print("debug: ")super.log(msg)}
}

8、混入

如果这是A开发的代码,B在用的时候,觉得之前extends ConsoleLogger不完善,还需要扩展其他的trait,但是联合开发的话,一般都不要随便修改别人的代码。
​但是还是想要增加新的功能,那么应该怎么做呢,一种方式是新写一个类继承A写的类,同时又扩展新的的功能,但是这种方法略微麻烦一点,所以这里在scala中使用了混入这样一个概念去处理。
在运行时去扩展一个特质,如下,便让B写的对象在原有的基础之上增加新的功能,对原先的类没有侵入。

?:
val mmp = new MainOperation with MyTrait //scala特质的混入 mix in
mmp.debug("dafaff")
mmp.show()
trait MyTrait {def show(): Unit = {println("江上如此多娇,引无数英雄尽折腰!")}
}

scala学习第二篇之面向对象相关推荐

  1. Elasticsearch学习第二篇--常用的几种搜索方式

    Elasticsearch学习第二篇--常用的几种搜索方式 一.Query String Search 查询全部 条件查询 二.Query DSL 查询全部 条件查询 三.Query Filter 四 ...

  2. TLS协议学习-第二篇-握手协议

    TLS协议学习第二篇,内容来自:https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-200 ...

  3. Android基础学习第二篇—Activity

    写在前面的话: 1. 最近在自学Android,也是边看书边写一些Demo,由于知识点越来越多,脑子越来越记不清楚,所以打算写成读书笔记,供以后查看,也算是把自己学到所理解的东西写出来,献丑,如有不对 ...

  4. [Python]学习基础篇:面向对象编程

    面向对象编程 是种具有对象概念的程序编程典范,同时也是一种程序开发的抽象方针.它可能包含数据.属性.代码与方法.对象则指的是类的实例.它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用 ...

  5. C++学习(第二篇)//最详细C++运算符经验

    c++运算符 //少年遥想得山田,请赶在日落下山前. 定义:运算符是一种告诉编译器执行特定的数学或逻辑操作的符号,C++ 内置了丰富的运算符. 目录 基础知识 基本概念 组合运算符和运算对象 重载运算 ...

  6. Scala学习第一篇

    Spark是发源于美国加州大学伯克利分校AMPLab的集群计算平台,它立足于内存计算,性能超过Hadoop百倍,从多迭代批量处理出发,兼收并蓄数据仓库.流处理和图计算等多种计算范式,是罕见的全能选手. ...

  7. JNI与NDK学习第二篇-----应用篇

    2019独角兽企业重金招聘Python工程师标准>>> 1.安装配置NDK 1). 解压NDK的zip包到非中文目录(最好英文目录不要带空格)     2). 配置path : 解压 ...

  8. UI学习第二篇 (控件)

    UIbutton 也是一个控件,它属于UIControl 用的最多的就是事件响应 1. //创建按钮对象 UIButton * _botton = [UIButton buttonWithType:U ...

  9. python学习[第二篇] 基础二

    控制结构 if 语句 # only if blockif condition:if_true_block# if_else blockif condition:if_true_block else:i ...

最新文章

  1. 我是如何将网站全站启用Https的?-记录博客安装配置SSL证书全过程
  2. 在dos下用csc命令编译,提示“csc不是内部或外部命令,也不是可运行的程序... ”
  3. 华为宣布:免费培养8000名嵌入式开发者!学习免费!实践免费!辅导免费!
  4. 二进制数据结构:JavaScript中的树和堆简介
  5. 数据库学习--主从复制
  6. 深入浅出mysql笔记
  7. python键盘输入字典类型_python数据类型——字典类型
  8. 使用transmission下载BT
  9. Photoshop插件-黑白(三)-脚本开发-PS插件
  10. ie浏览器java 脚本下载_用IE浏览器时不断出现Java活动脚本功能出错问题
  11. 科学与信息化杂志科学与信息化杂志社科学与信息化编辑部2022年第15期目录
  12. Redis技术贴一览表
  13. java 输入地址_Java输入邮件地址
  14. JavaScript的json和Array及Array数组的使用方法
  15. Interview Vocabulary Summary
  16. Coremail邮件安全:如何防范校园邮件新威胁
  17. OpenCV:07图像轮廓
  18. In aggregated query without GROUP BY, expression #2 of SELECT list contains nonaggregated column
  19. 2019 GDUT Winter Training III
  20. GDAL使用DEM数据计算坡度坡向

热门文章

  1. 计算机专业技术考核表,专业技术人员量化考核计分表(3类).doc
  2. 招聘 | 腾讯优图(深圳)实验室实习生招聘
  3. ubuntu切换root用户出错:sudo:无法切换为root组ID:不允许的操作
  4. input获取焦点vue_Vue点击显示文本框并获取焦点
  5. 经典软件测试基础面试问答
  6. 很牛的语文老师,很牛的分享!
  7. tp5.1接入支付宝支付接口
  8. 酷睿i9 12900k参数 功耗 i912900k核显什么水平
  9. C语言不同进制的标志
  10. Kotlin - byte转 int