面向对象编程

 

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. JS函数可以再添加属性(包括方法)

    1 前言 JS函数可以再添加属性(包括方法),这个有点有趣,记录一下. 2 代码 <!DOCTYPE html> <html> <head> <title&g ...

  2. Penettation testing with the bush Shell

    1.  Network Reconnaissance first we can use the command to gather the site information by whois eg : ...

  3. 编译linux内核前用make menuconfig设置时 Unable to find the ncurses ibraries的解决办法

    今天在更新CentOS或者Ubuntu的内核时,执行make menuconfig可能看如这样的错误: *** Unable to find the ncurses libraries or the ...

  4. JS 的骚操作

    一.强制类型转换 1.1string强制转换为数字 //可以用*1来转化为数字((实际上是调用.valueOf方法) 然后使用Number.isNaN来判断是否为NaN,或者使用 a !== a 来判 ...

  5. 大数据项目之_15_帮助文档_NTP 配置时间服务器+Linux 集群服务群起脚本+CentOS6.8 升级到 python 到 2.7

    一.NTP 配置时间服务器1.1.检查当前系统时区1.2.同步时间1.3.检查软件包1.4.修改 ntp 配置文件1.5.重启 ntp 服务1.6.设置定时同步任务二.Linux 集群服务群起脚本2. ...

  6. VB开发类似IIS简易的WebServer,代码不到100行

    最近遇到三个人问关于VB写网页服务器的问题,所以今天抽时间写一下,演示其实没有多复杂. 代码里自定义的方法只有四个,没有公共变量绕来绕去,该注释的也都注释了. 想扩展更复杂的功能,就需要自己补脑HTT ...

  7. ZAB协议与Paxos算法

    ZooKeeper并没有直接采用Paxos算法,而是采用一种被称为ZAB(ZooKeeper Atomic Broadcast)的一致性协议 ZooKeeper是一个典型的分布式数据一致性的解决方案, ...

  8. 两个排序链表的合并(Easy)

    问题来源:选自leetcode 21:合并两个有序链表 问题描述: 题目给定信息: 给定两个有序链表,把两个链表合并成一个链表,并且合并后的链表依然是有序的.这两个链表中允许有重复元素 问题分析: 设 ...

  9. Javascript Date类型

      Date 类型使用自 UTC 1970 年 1 月 1日 午夜 开始经过的毫秒数来保存日期.   创建日期对象 var now = new Date();//获取当前日期   Date.parse ...

  10. Python练手例子(7)

    37.对10个数进行排序. 程序分析:可以利用选择法,即从后9个比较过程中,选择一个最小的与第一个元素交换,下次类推,即用第二个元素与后8个进行比较,并进行交换. #python 3.7 if __n ...