面向对象编程

 

11.1 object类

11.1.1定义一个简单的类

 

11.1.2 field的getter与setter

定义类包含,定义类的field及方法。其格式如下

class ClassName{ // 其中类名首字母要大写

private var name = "Hys" // private修试符说明此变量只对本类有效

def sayHello(){ print("Hello," + name)

def getName = name // 获取name 的值

}

创建类的对象,并调用其方法

val field_name = new ClassName // 创建类对象

field_name.sayHello() // 调用类方法

print(field_name.getName()) // 调用类成员

 

11.1.3 构造函数-constructor

 

11.1.4 内部类

 

11.2 对象

 

 

11.3 继承

继承的主要有点:可以减少代码量

11.3.1 关键字extends

*父类中用final修饰的field和method是无法被子类继承的

示例代码:

class Person {

         private var name = "George"

def getName = name

}

class Student extends Person {

private var score = "A"

         def getScore = score

}

11.3.2 子类覆盖父类field和method

    1.override关键字

        使用此关键字覆盖可以帮助发现代码里的错误

    2.父类方法被覆盖之后还可以使用super调用父类方法

    示例代码:

        class Person{

private var name = "George"

def getName = name

}

class teacher extends Person{

private var age = 20

def getAge = age

override def getName = "Hello " + super.getName

}

    3. override field

    示例代码:

class Person{

val name:String = "Hys"

def age:Int = 20

}

class Teacher extends Person{

override val name:String = "George"

        override val age:Int = 30

}

    4.isInstanceOf 和 asInstanceOf

     isInstanceOf :判断指定对象是否为指定类或其子类的对象,如果对象是null则一定返回false

     asInstanceOf:将指定对象转换为指定类型

    示例代码:

        class Person

class Teacher extends Person

 

val p:Person = new Teacher

val t:Teacher = null

if(p.isInstanceOf[Teacher]) t = p.asInstanceOf[Teacher]

    5.getClass 和 classOf[类]

     p.getClass 可以获取对象被实例化的类型

     classOf[类] 可以获取精确的类

    示例代码:

    p.getClass == classOf[Person] 判断p是否是被实例化为Person类型

    p.getClass == classOf[Teacher]

6. 模式匹配进行类型判断

     *判断对象是否和该类及其子类的对象

p match{

case per:Person => println("it's Person's object")

case _ => println("Unknown type")

}

    7.关键字protected

     *父类中使用protected 修试的field 和 method在子类中直接就可以访问。

     *当使用protected[this]时只能在"子类 当前对象"中访问父类的,其它对象不可以,包括同类对象。

    代码示例:

    class Person{

protected var name:String = "Hys"

}

class Teacher extends Person{

def sayHello() = {println("Hello " + name)}

}

val t = new Teacher

t.sayHello

8. 调用父类的构造函数constructor

*只能在子类的主constructor中调用父类的constructor;原因是辅构造函数只能调用本类的主构造函数或者辅构造函数

* 父类中接收的参数,子类中就不要用任何val 或者var 来修饰,否在认为是要覆盖父类的field

示例代码:

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

class Teacher(name:String, age:Int, var score:Double) extends Person(name,age){

def this(name:String){

this(name,0,0)

}

def this(age:Int){

this("Hys",age,0)

}

}

8.调用父类的constructor

* 每个类的辅助构造函数(constructor)只能调用本类的辅助constructor或者主constructor,所以要调用父类构造函数必须使用子类的主构造函数。

*如果是父类中接收的参数,子类接收时就不要用var或者val 来修饰了,否则会认位是覆盖父类的field 。

示例代码:

Class Person(val name:String, val age:Int){

    Println("Person's name is " + name)

    Println("Person's age is " + age)

}

Class Teacher(name:String, age:Int, var score:Double) extends Person(name, age){

    def this(name:String){

this(name:String)

}

def this(age:Int){

this("Hys ",age,0)

}

Println(name + " " + age + " " + score)

}

val t = new Teacher("George", 20, 100)

Person's name is George

Person's age is 20

George 20 100.0

9.匿名内部类

*匿名子类:定义的没有名字的子类,同时直接创建其对象,然后将对象的引用赋予一个变量。然后匿名子类的对象也可以传给其它函数。

示例代码:

class Person(protected val name:String){

def sayHello = "Hello, I'm " + name

}

val p = new Person("Hys") {

override def sayHello = "Nice to meet you " + name} //匿名子类

def greeting(p:person{def sayHello:String}){ //把匿名子类当成参数传给函数

println(p.sayHello)

}

greeting(p) //调用匿名子类实例

10.抽象类

*抽象方法:定义时只有方法名和方法类型的方法。

*抽象类:包含抽象方法的类就是抽象类,即只要类中有一个抽象方法此类就为抽象类。

*抽象类必须用abstract关键词修饰。

*抽象类不可以被实例化。

*在子类中覆盖抽象类的方法时不需要用override关键字。

代码示例:

abstract class Person(){ //定义抽象类

def sayHello:String

}

class Teacher(name:String) extends Person{ //继承抽象类

def sayHello:String = {println("Hello" + name ); name} // 覆盖父类方法

}

val t = new Teacher("Hys")

t.sayHello

11.抽象field

*抽象field:定义field时只给出类型没有给出初值,这样的field就是抽象field。

*Scala会根据自己的规则为var或者val类型的field生成对应的getter和setter方法,但是父类中是没有field的,就父类中的抽象field不占内存。

*子类必须覆盖父类的抽象field。

*子类覆盖父类的抽象field不需要override关键字。

示例代码(子类不覆盖父类抽象field报错):

Abstract class Person{ //定义抽象类

Val name:String

}

class Teacher extends Person{} //子类不重写代码,报错

(子类正常继承父类)

class Teacher extends Person{

val name:String = "Hys" // 覆盖父类抽象方法

}

(子类把父类的抽象field继承为抽象field操作)

class Teacher extends Person{ val name:String } // 把父类抽象方法继承为抽象方法,如果不用abstract修饰子类会有报错

abstract class Teacher extends Person{ val name:String} //正确的把父类抽象方法继承为抽象方法

11.4 Trait

11.4.1基础知识

1.将trait作为接口使用

*类使用关键字extends继承

*与Java中的接口一样

*抽象方法不需要overrid管家你

*Scala不支持对类进行多继承,但可以多继承trait,使用with关键字

代码示例:

trait HelloTrait{

def sayHello(name:String)

}

trait MakeFriendsTrait{

def makeFriends(p:Person)

}

class Person(val name:String) extends HelloTrait with MakeFriendsTrait with Cloneable with Serializable{

def sayHello(name:String) = println("Hello " + name)

def makeFriends(p:Person) = println("Hello, my name is " + name + " your name is " + p.name)

}

2.在trait中定义具体方法

*就像类中定义方法一样

*不同之处在子类中调用是直接使用方法名就可以

trait computer{

def playVideo()={println("Play video")}

}

class Person extends computer{

playVideo()

def play()={playVideo()}

}

val p = new Person

p.playVideo

3.在trait中定义具体字段

*与类继承不同,trait定义的具体字段直接添加到了继承它的类中

trait Person{

val eyeNum:Int = 2

}

class Teacher(val name:String, val age:Int) extends Person{

println("Hello "+ name + ", you have " + eysNum + "eyes")

}

4.在trait中定义抽象字段

*trait中可以定义抽象字段,同时trait中的具体方法可以基于抽象字段来写,只不过继承trait的类必须覆盖抽象的field,提供具体的值

trait SayHello {

val name:String

def sayHello()={"Hello " + name}

}

 

class Person extends SayHello{

val name:String = "Hys" //覆盖trait中抽象字段

def makeFriends(p:Person){

sayHello()

println(name + ", nice to meet you")

}

}

11.4.2高级知识

1.为实例对象混入trait

*只有本对象可以调用

trait Loger{

def log(msg:String){print("loger trait")}

def logTrait(){println("loger trait")}

}

trait MyLoger extends Loger{

override def log(msg:String){println("log:" + msg)}

}

class Person(val name:String) extends Loger{

def sayHello{println("Hi,I'm " + name );log("sayHello is invoked!")}

}

val p2 = new Person("George") with MyLoger //动态混入trait

val p1 = new Person("Hys")

scala> p2.logTrait()

trait

scala> p1.log("")

loger trait

2.trait调用链

*继承同一个trait的多个trait,在具有相同method的最后都执行super.method,就可以从右向左依次执行每个被继承的多个trait中相同的方法,从而实现调用链。

代码示例:

trait Loger{

def vs(){}

def kk(){}

}

trait PersonReady extends Loger{

override def vs(){

println("I am ready")

super.vs() //执行此方法

}

}

trait PersonGo extends Loger{

override def vs(){

println("Please go!")

super.vs()

}

}

trait PersonEnd extends Loger{

override def vs(){

println("To be end!")

super.vs()

}

}

class PersonVs extends PersonEnd with PersonGo with PersonReady{

def aURD(name:String){

println("Are you ready")

vs() //执行调用链

}

}

3.在trait中覆盖抽象方法

*当子trait调用super.method_name 时要要给子trait的方法加上abstract override修饰

示例代码1(无super.method_name调用):

trait Logger{

def log(msg:String)

}

trait Mylogger extends Logger{

override def log(msg:String){}

}

示例代码2(有super.method_name调用):

trait Logger{

def log(msg:String)

}

trait Mylogger extends Logger{

abstract override def log(msg:String){super.log("kk")} // 当调用super.method_name时要用abstract修饰

}

4.混合使用trait的具体方法和抽象方法

*可以让trait中具体方法依赖于抽象方法,而抽象方法则放到继承trait的类中去实现,就好像是一个模板

trait Valid{

def getName:String //在trait中定义抽象方法

def valid:Boolean={ //在trait中定义具体方法

getName == "Hys"

}

}

class Person(val name:String) extends Valid{

println(valid) //此语句需要执行的函数及次序是construceto->getName->vaild

def getName = {println("Get the name.")

name

}

}

5.trait的构造机制

*trait中不包含在任何方法中的代码就是trait的构造代码

*构造代码执行优先级 父类构造函数->多个trait从左到右依次执行->父trait的构造代码->子类的构造函数

示例代码:

class Person{print("Person's constructor")}

trait Logger{println("\n Logger constructor")}

trait Logger{println("\n Logger constructor")}

trait TimeLogger extends Logger{println("TimeLogger")}

class Teacher extends Person with TimeLogger with MyLogger{println("Tescher class")}

实例化演示:

scala> val t = new Teacher

Person's constructor

Logger constructor

TimeLogger

Mylogger constructor

Tescher class

6.trait字段的初始化

*trait不可以接收带参数的构造函数,如果想使用trait初始化field,可以使用Scala的提前定义特性

示例代码:

trait SayHello{

val msg:String //需要初始化的字段

println(msg.toString) // 对初始化字段的调用

}

class Person

val p = new Person with SayHello //报错

val p = new {val msg:String = "Hys" //提前定义

} Person with SayHello

或者

class Person extends { val msg:String = "Hys" //提前定义

} with SayHello

还有办法就是使用lazy value

*如果不用lazy仍然会报异常

trait SayHello {

lazy val msg:String = null

println(msg:toString)

}

class Person extends SayHello //继承的时候没有用lazy,实例化时有异常发生

val p = new Person //有异常跳出

class Person extends SayHello{ override lazy val msg:String = "George"} //使用lazy覆盖该field,实例化时正常

val p = new Person

7.让trait继承类

*trait也可以继承自class,此时class就回成为所有继承该trait的类的父类

示例代码:

class Hys { println("class Hys")}

trait George extends Hys {println("trait George")} //trait 继承类

class Person extends George{println("class Person")} //之类继承继承了类的trait,此时trait继承的类相当于继承了该trait的父类。

scala> val p = new Person

class Hys

trait George

class Person

由构造函数执行内容和顺序可知Hys类是Person的父类

Spark学习笔记11面向对象编程的更多相关文章

  1. javascript 学习笔记之面向对象编程(一):类的实现

    ~~想是一回事,做是一回事,写出来又是一回事~~一直以来,从事C++更多的是VC++多一些,从面向过程到面向对象的转变,让我对OO的编程思想有些偏爱,将一个客观存在的规律抽象出来总是让人比较兴奋,通过 ...

  2. JavaSE学习笔记05面向对象编程01

    面向对象编程01 java的核心思想就是OOP 面向过程&面向对象 面向过程思想: 步骤清晰简单,第一步做什么,第二步做什么...... 面向过程适合处理一些较为简单的问题 面向对象思想: 物 ...

  3. python 学习笔记7 面向对象编程

    一.概述 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发"更快更好更强..." ...

  4. C++ Primer 学习笔记_67_面向对象编程 --转换与继承、复制控制与继承

    面向对象编程 --转换与继承.复制控制与继承 I.转换与继承 引言: 由于每一个派生类对象都包括一个基类部分,因此能够像使用基类对象一样在派生类对象上执行操作. 对于指针/引用,能够将派生类对象的指针 ...

  5. javascript 学习笔记之面向对象编程(二):继承&多态

    ~~接上篇~~上一篇实现了类的实现以及类成员变量和方法的定义,下面我们来了解下面向对象中两个最重要的特性:继承和多态. 继承 js中同样可以实现类的继承这一面向对象特性,继承父类中的所有成员(变量和属 ...

  6. C++ Primer 学习笔记_69_面向对象编程 --继承情况下的类作用域

    面向对象编程 --继承情况下的类作用域 引言: 在继承情况下,派生类的作用域嵌套在基类作用域中:假设不能在派生类作用域中确定名字,就在外围基类作用域中查找该名字的定义. 正是这样的类作用域的层次嵌套使 ...

  7. C++ Primer 学习笔记_72_面向对象编程 --句柄类与继承[续]

    面向对象编程 --句柄类与继承[续] 三.句柄的使用 使用Sales_item对象能够更easy地编写书店应用程序.代码将不必管理Item_base对象的指针,但仍然能够获得通过Sales_item对 ...

  8. python学习笔记(七):面向对象编程、类

    一.面向对象编程 面向对象--Object Oriented Programming,简称oop,是一种程序设计思想.在说面向对象之前,先说一下什么是编程范式,编程范式你按照什么方式来去编程,去实现一 ...

  9. python自动化测试学习笔记-7面向对象编程,类,继承,实例变量,邮件

    面向对象编程(OOP)术语: class TestClass(object):   val1 = 100       def __init__(self):     self.val2 = 200   ...

随机推荐

  1. 六.ansible批量管理服务

    期中集群架构-第六章-ansible批量管理服务介绍====================================================================== 01. ...

  2. vertx实例的fileSystem文件系统模块

    初始化 //根据OS区分实现 System.getProperty("os.name").toLowerCase(); Utils.isWindows() ? new Window ...

  3. .NET Core 添加Java 服务引用(WebService) 曲折历程(一)

    背景: 需要在HangFire定时任务中加入请求Java开发的WebService接口.定时获取数据同步数据.现有的代码是在VS2017 ,.Net Core 下创建的,添加WS发现系统不支持. 在C ...

  4. gflags_static.lib 无法解析的外部符号 __imp__PathMatchSpec

    在用gflags库时生成提示 无法解析的外部符号 __imp__PathMatchSpec   解决办法:Add "shlwapi.lib" to "Project - ...

  5. IP网际协议

    IP分类 IP地址分为网络号和主机号,5类不同的IP地址格式如下: A类地址每个网段内最多有224个,也就是16,777,214个. B类地址每个网段内最多有216个,也就是65535个. C类地址每 ...

  6. 不装插件,查看.rp文件

    AxShare国内平台地址:http://share.axure.org临时急用可以使用公用帐户.用户名:axure@webppd.com,密码:webppd123 上传.rp文件,点击 url 地址 ...

  7. Linux下如何查看系统启动时间和运行时间以及安装时间

    1.uptime命令输出:16:11:40 up 59 days, 4:21, 2 users, load average: 0.00, 0.01, 0.00 2.查看/proc/uptime文件计算 ...

  8. c# 向数据库插数据超过1000条

    今天想着如何大批量插入数据到数据库中  最开始的想法是使用insert循环插入 但每次都要创建数据库连接 这是非常消耗时间和消耗资源的事.后在网上看到了说使用SqlBulkCopy ,就看了看文档和别 ...

  9. Round#534 div.2-C Grid game

    http://codeforces.com/contest/1104/problem/C 好厉害的题~ 只要把竖着的放在第一第二行,横着的放在第三/第四行就行. 哦吼,大半夜脑子迷糊地看英文的脑筋急转 ...

  10. ISP PIPLINE (三) BPC

    what is the Bad Pixel? 坏点为死点,也就是基本不随照度变化呈现光电线性转换的关系.表现为暗态常亮,亮态常暗. 坏点分类:静态坏点:亮坏点,暗坏点.                 ...