目录
一、⾯向对象的概念
如何理解抽象?
定义⼀个类,实际上就是把⼀类事物的共有的属性和⾏为提取出来,形成⼀个物理模型
(
模板
)
。这种研究问题的⽅ 法称为抽象。
⾯向对象编程有三⼤特征:
封装、继承和多态
。
封装
(encapsulation)
就是把抽象出的数据和对数据的操作封装在⼀起,数据被保护在内部,程序的其它部分只有通过被授权的操作(
成员⽅法
)
,才能对数据进⾏操作。
封装的理解和好处
- 隐藏实现细节,可以对数据进⾏验证,保证安全合理
如何体现封装?
-
对类中的属性进⾏封装
-
通过成员⽅法、包实现封装
封装的实现步骤 :
- 将属性进⾏私有化提供⼀个公共的set⽅法,⽤于对属性判断并赋值
def setXxx(参数名 : 类型) : Unit = {
//此处可以加⼊数据验证的业务逻辑
属性 = 参数名
}
提供⼀个公共的get⽅法,⽤于获取属性的值
def getXxx() [: 返回类型] = {
return 属性
}
二、Java类的定义
大数据一般都会学java我们看看Java的吧
类和对象的区别和联系:
- 类是抽象的,概念的,代表⼀类事物,⽐如⼈类、猫类...
- 对象是具体的,实际的,代表⼀个具体事物
- 类是对象的模板,对象是类的⼀个个体,对应⼀个实例。
想下java类的定义:
1)Java中类和对象的概念
2)Java中类如何定义,定义类,属性,getter,setter⽅法,构造器,其他⾏为等。
3)定义Java类需要考虑的问题:修饰符 public protected default private
修饰类使⽤ public 或者 default
为什么类只需要 public 或者 default 修饰?因为外部类的上⼀单元是包,所以外部类只有两个作⽤域:同包,任何位置。因此,只需要两种控制权限:包控制权限 和公开访问权限,也就对应两种控制修饰符:public 和默认 (default) 。
什么时候会使⽤ private 或者 protected 修饰类? 内部类。
修饰符
|
当前类
|
同⼀个包内
|
⼦孙类
|
其他包
|
public
|
Y
|
Y
|
Y
|
Y
|
protected
|
Y
|
Y
|
Y
|
N
|
(default)
|
Y
|
Y
|
N
|
N
|
private
|
Y
|
N
|
N
|
N
|
4)Java中定义类:
-
定义类
-
定义类的字段
-
定义字段的getter和 setter ⽅法(属性)
-
定义构造⽅法
-
定义其他⽅法
-
最后考虑属性、⽅法和类的修饰符
三、Scala定义类的属性
/*
//在Scala中,类并不⽤声明为public。
//Scala源⽂件中可以包含多个类,所有这些类都具有公有可⻅性。
在scala中,类并不⽤声明为public
如果没有定义构造器,类会有⼀个默认的⽆参构造器
var修饰的变量,对外提供getter setter⽅法
val修饰的变量,提供getter⽅法,没有setter⽅法
*/
class Student {
//⽤var修饰的变量,默认同时有公开的getter⽅法和setter⽅法
//Scala中声明⼀个属性,必须显示的初始化,然后根据初始化数据的类型⾃动推断,属性类型可以省略
//_表示⼀个占位符,编译器会根据你变量的具体类型赋予相应的初始值
//使⽤占位符,变量类型必须指定
//类型 _ 对应的值
//Byte Short Int Long默认值 0
//Float Double 默认值 0.0
//String 和 引⽤类型 默认值 null
//Boolean 默认值 false
var name = "tom"
var nickName:String = _
//如果赋值为null,则⼀定要加类型,因为不加类型, 那么该属性的类型就是Null类型.
//var address = null
//改为:
var address:String = null
//⽤val修饰的变量是只读属性的,只带getter⽅法但没有setter⽅法
//(相当与Java中⽤final修饰的变量)
//val修饰的变量不能使⽤占位符
val age = 10
//类私有字段,有私有的getter⽅法和setter⽅法,只能在类的内部使⽤
//其伴⽣对象也可以访问
private var hobby: String = "旅游"
//对象私有字段,访问权限更加严格的,Person类的⽅法只能访问到当前对象的字段
private[this] val cardInfo = "123456"
}
四、Scala⾃定义get和set⽅法
重要提示:⾃⼰⼿动创建变量的getter和setter⽅法需要遵循以下原则:
0) 将成员变量定义为私有1) 字段属性名以 “_” 作为前缀,如定义: _x2) getter ⽅法定义为: def x = _x3) setter ⽅法定义时,⽅法名为属性名去掉前缀,并加上后缀,后缀是: “x_=” ,如例⼦所示
class Point {
private var _x = 0
private var _y = 0
private val bound = 100
def x = _x
def x_= (newValue: Int): Unit = {
if (newValue < bound) _x = newValue else printWarning
}
def y = _y
def y_= (newValue: Int): Unit = {
if (newValue < bound) _y = newValue else printWarning
}
private def printWarning = println("WARNING: Out of bounds") }
object Point{
def main(args: Array[String]): Unit = {
val point1 = new Point
point1.x = 99
point1.y = 101 // prints the warning
}
}
五、Bean属性
# JavaBean 规范- 公有类- ⽆参的公有构造⽅法- 私有字段- getter&setter
JavaBean
规范把
Java
属性定义为⼀堆
getFoo
和
setFoo
⽅法。类似于
Java
,当你将
Scala
字段标注为
@BeanPropert
y 时,getter
和
setter
⽅法会⾃动⽣成
import scala.beans.BeanProperty
object exam1 {
def main(args: Array[String]): Unit = {
val per: Person = new Person
per.name = "zhagnsan"
per.setName("lisi") //BeanProperty⽣成的setName⽅法
println(per.getName) //BeanProperty⽣成的getName⽅法
}
}
class Person {
@BeanProperty var name:String = _ }
上述类
Person
中由
@BeanProperty
⽣成了四个⽅法:
1. name: String2. name_= (newValue: String): Unit3. getName(): String4. setName (newValue: String): Unit
六、Scala定义类的构造器
Scala
类的构造器作⽤是完成对新对象的初始化,构造器没有返回值。构造器包括: 主构造器和辅助构造器。
Scala
构造器的语法:
class 类名(形参列表) { // 主构造器
// 类体
def this(形参列表) { // 辅助构造器 }
def this(形参列表) { //辅助构造器可以有多个... }}
//辅助构造器函数的名称this, 可以有多个,编译器通过不同参数来区分.
1) 主构造的参数直接放置于类名之后
定义类:(构造器中的字段总是私有,
private
修饰
getter
或
setter
的访问级别)
private var name: String
私有字段,私有的
getter
和
setter
⽅法
var name: String
私有字段,公有的
getter
和
setter
⽅法
private val name: String
私有字段,私有的
getter
⽅法
val name: String
私有字段,公有的
getter
⽅法
class ClassConstructor (var name: String, private var price: Double){
def myPrintln = println(name + "," + price)
}
//执⾏:
val classConstructor = new ClassConstructor("《傲慢与偏⻅》", 20.5)
classConstructor.myPrintln
2) 主构造器会执⾏类定义中的所有语句
//定义类:
class ClassConstructor2(val name: String = "", val price: Double = 0) {
println(name + "," + price) }
//执⾏:
val classConstructor2 = new ClassConstructor2("aa", 20)
val classConstructor2_2 = new ClassConstructor2()
3)
如果不带
val
和
var
的参数⾄少被⼀个⽅法使⽤,该参数将⾃动升级为字段
,这时,
name
和
price
就变成了类的不 可变字段,⽽且这两个字段是对象私有的,这类似于
private[this] val
字段的效果。否则,该参数将不被保存为字段,即实例化该对象时传⼊的参数值,不会被保留在实例化后的对象之中
class ClassConstructor (name: String, price: Double){
def myPrintln = println(name + "," + price) }
object test {
def main(args: Array[String]): Unit = {
val classConstructor = new ClassConstructor("《傲慢与偏⻅》", 20.5)
classConstructor.myPrintln
}
}
private[this] val
修饰的对象私有字段不允许在该类的其他对象中访问:
class Dog(name:String) { //name是对象私有字段
def say()={
println(s"i am $name")
}
def look(dog:Dog)={
println(s"$name say: hello ! ${dog.name}") //错误 dog.name是对象私有字段,不允许当前对象访问
}
}
object DogTest extends App{
val dog=new Dog("bbc")
dog.say()
dog.look(new Dog("cnn"))
}
主构造器参数⼩结:
主构造器参数
|
⽣成的字段/⽅法
|
String
|
对象私有字段。如果没有⽅法使⽤name
,则没有该字段
|
private val/var name: String
|
私有字段,私有的
getter
和
setter
⽅法
|
var name: String
|
私有字段,公有的
getter
和
setter
⽅法
|
@BeanProperty val/var name: String
|
私有字段,公有的
Scala
版和
Java
版的
getter
和
setter
⽅法
|
4)
可以通过
private
设置私有的主构造器
//私有主构造器⽆法调⽤,需要定义辅助构造器创建相应的对象
class ClassConstructor private (var name: String, private var price: Double){
def myPrintln = println(name + "," + price) }
object TestClassConstructor{
def main(args: Array[String]): Unit = {
val classConstructor = new ClassConstructor("《傲慢与偏⻅》", 20.5) //编译错误
classConstructor.myPrintln
}
}
5)
辅助构造器名称为
this
,通过不同参数进⾏区分,每⼀个辅助构造器都必须以主构造器或者已经定义的辅助构 造器的调⽤开始,即需要放在辅助构造器的第⼀⾏
class Person {
private var name = ""
private var age = 0
//辅助构造器的声明不能和主构造器的声明⼀致,会发⽣错误(即构造器名重复)
def this(name: String) {
this()
this.name = name
}
def this(name: String, age: Int) {
this(name)
this.age = age
}
def description = name + " is " + age + " years old"
}
this.name 表示访问当前对象的 name 字段,可以使⽤别名替换 this 。
class Person{
self=> //self 等价于 this ; 需要出现在类的第⼀句
private var name = ""
private var age = 0
def this(name: String) {
this()
self.name = name
}
def this(name: String, age: Int) {
this(name)
self.age = age
}
def description = name + " is " + age + " years old"
}
七、cala创建对象和访问属性
创建对象的语法:
val | var
对象名
[
:类型
] = new
类型
()
如果我们不希望改变对象的引⽤
(
即:内存地址
)
,应该声明为
val
性质的,否则声明为
var
,
scala
设计者推荐使 ⽤ val
,因为⼀般来说,在程序中,我们只是改变对象属性的值,⽽不是改变对象的引⽤。
访问属性的语法:
对象名
.
属性名
object Test1 {
val name: String = "zhangsan"
def main(args: Array[String]): Unit = {
//调⽤空参构造器,可以加()也可以不加
val student = new Student()
student.name = "lisi"
//变量中使⽤val修饰的变量不能更改
//student.age = 50
println(student.name)
println(student.age)
println(Test1.name) //Test1也是对象,称单例对象
}
}