封装就是把抽象出的数据和对数据的操作封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作(成员方法),才能对数据进行操作。
java封装操作如下:
定义一个对象
class Person{
/**
* id
*/
private var id:Int=_
/**
* 姓名
*/
private var name:String=_
/**
* 年龄
*/
private var age:Int=_
/**
* 性别
*/
private var sex:Char=_
}在 java 中可以通过第三方工具快速生成 get/set方法;在scalal中(idea)不行。若需要添加get/set方法需要自己写。
如:
def getId():Int=this.id
def setId(id:Int)=this.id=id在scala 为了符合JavaBean规范,专门提供了一个 注解 @BeanProperty 用于对属性生成 getter/setter 方法。
使用 @BeanProperty 是有限制的。
private 修饰val class Person{
/**
* id
*/
@BeanProperty var id:Int=_
/**
* 姓名
*/
@BeanProperty var name:String=_
/**
* 年龄
*/
@BeanProperty var age:Int=_
/**
* 性别
*/
@BeanProperty var sex:Char=_
}使用
def main(args: Array[String]): Unit = {
val p=new Person()
p.setId(1001)
p.setName("张三")
p.setAge(19)
p.setSex('男')
val info=s"id=${p.getId},姓名=${p.getName},年纪=${p.getAge},性别=${p.getSex}"
println(info) // id=1001,姓名=张三,年纪=19,性别=男
}疑问?使用get/set 不就是用来访问和操作私有属性的吗? 使用 @BeanProperty 居然还必须时 public 那么定义该注解的有何用?
如下:不使用 get/set 可以进行操作。
def main(args: Array[String]): Unit = {
val p=new Person()
p.id=1001
p.name="张三"
p.age=19
p.sex='男'
val info=s"id=${p.id},姓名=${p.name},年纪=${p.age},性别=${p.sex}"
println(info) // id=1001,姓名=张三,年纪=19,性别=男
}有没有小伙伴和我有一样的疑问?
@BeanProperty 只是用于符合JavaBean规范,java很多api都遵循这个规范,scala若要去调用,也不得不去准寻这规范。严格意义上来说,scala的封装并不是封装。
还是用个案例来说明吧。json 可以用于将 JavaBean转为JSON或者将 JSON格式数据转为JavaBean。
导入 fastjson
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.72</version>
</dependency>对象 转 json
def main(args: Array[String]): Unit = {
val p=new Person()
p.id=1001
p.name="张三"
p.age=19
p.sex='男'
// 对象 转 json
val jsonStr=JSON.toJSON(p).toString
println(jsonStr) // {"sex":"男","name":"张三","id":1001,"age":19}
}若没有 get/set 方法,将无法解析 json 转对象
class Person{
/**
* id
*/
var id:Int=_
/**
* 姓名
*/
var name:String=_
/**
* 年龄
*/
var age:Int=_
/**
* 性别
*/
var sex:Char=_
}
def main(args: Array[String]): Unit = {
// 对象 转 json
// classOf[Person] 用于获取 Person 的 class
val p:Person=JSON.parseObject("""{"sex":"男","name":"张三","id":1001,"age":19}""",classOf[Person])
val info=s"id=${p.id},姓名=${p.name},年纪=${p.age},性别=${p.sex}"
println(info) // id=0,姓名=null,年纪=0,性别=
}重新指定 @BeanProperty
class Person{
/**
* id
*/
@BeanProperty var id:Int=_
/**
* 姓名
*/
@BeanProperty var name:String=_
/**
* 年龄
*/
@BeanProperty var age:Int=_
/**
* 性别
*/
@BeanProperty var sex:Char=_
}
def main(args: Array[String]): Unit = {
// 对象 转 json
// classOf[Person] 用于获取 Person 的 class
val p:Person=JSON.parseObject("""{"sex":"男","name":"张三","id":1001,"age":19}""",classOf[Person])
val info=s"id=${p.id},姓名=${p.name},年纪=${p.age},性别=${p.sex}"
println(info) // id=1001,姓名=张三,年纪=19,性别=男
}关于 @BeanProperty 注解,我也不太明白为什么开发者会这么设计,对于我来说就是不合理。但他的作用就是用于兼容JavaApi。
java中的继承 语法:
[修饰符] class 类名 extends 父类名{类体}
特性:
extends 关键字用于继承final的类不能被继承,private 修饰的属性和方法。scala中的继承 语法:
class 类名[(参数列表)] extends 父类名[参数列表]
特性:
extends 关键字用于继承extends 并不是继承一个类的标志,也可用于 特质类上。private 修饰的不能被继承。定义
class Person{
var name="your name?"
def add(x:Int,y:Int)=x+y
}
class Student extends Person 调用
def main(args: Array[String]): Unit = {
val stu=new Student
println(stu.name) // your name?
println(stu.add(1,2)) // 3
}方法重写:
在 Person 中有个add 方法,可能该方法并不是我们想要,我需要的功能是 x-y 此时就需要对该方法进行重写。
在scala 中重写父类中的方法,需要使用 override 关键字修饰。
class Student extends Person {
// 重写 父类的 add 方法
override def add(x: Int, y: Int): Int = x-y
}调用:
def main(args: Array[String]): Unit = {
val stu=new Student
println(stu.name) // your name?
println(stu.add(1,2)) // -1
}属性重写 在scala中除了可以对方法进行重写外,还可以对属性进行重写
class Student extends Person {
name="王富贵"
override def add(x: Int, y: Int): Int = x-y
}
def main(args: Array[String]): Unit = {
val stu=new Student
println(stu.name) // 王富贵
println(stu.add(1,2)) // -1
}注意:以上这种不能称为重写,而只是在子类定义了一个与父类相同的属性,覆盖了父类中的属性,可以称为改了父类中该属性的值。 那么什么才叫属性重写呢?
val ,不能使用private 修饰。override 关键字。重新在Person中定义一个属性hobby
class Person{
var name="your name?"
val hobby="唱跳,rap"
def add(x:Int,y:Int)=x+y
}在Student中重新父类的 hobby 属性,比如打篮球
class Student extends Person {
name="坤坤"
override val hobby: String = "打篮球"
override def add(x: Int, y: Int): Int = x-y
}运行
def main(args: Array[String]): Unit = {
val stu=new Student
println(stu.name) // 坤坤
println(stu.hobby) // 打篮球
println(stu.add(1,2)) // -1
}温馨提示:没有冒犯任何姓名中带坤的人,不过我觉得,能看到此文章的人应该都是程序员吧?没有哪个程序员会是某垃圾的粉丝吧。
调用父类中的方法
在java中若要调用父类中的 方法,会使用supper 关键字,在scala中也是一样。
class Student extends Person {
name="坤坤"
override val hobby: String = "打篮球"
override def add(x: Int, y: Int): Int = {
// 调用父类中的 add 方法
println(s"supper add=:${super.add(x,y)}")
x-y
}
}构造器 继承中父子类的构造器知识点也是很重要的。
// 父类
class Person(val id:Int,val name:String){
}
// 子类
class Student(override val id:Int, override val name:String, age:Int) extends Person(id,name){
} class Person{
def this(id:Int,name:String){
this()
}
}
class Student(val id:Int, val name:String, age:Int) extends Person{
}也可以指定父类的副构造器;也是可以的。
class Person{
def this(id:Int,name:String){
this()
}
}
class Student(val id:Int, val name:String, age:Int) extends Person(id,name){
}supper 关键字,并且必须指定在子类的第一行。
如:class A{}
class B extends A{
// 调用父类构造器
public B(){
super();
}
}在scala中也是如此。此时有个,有个问题,在scala中定义副构造器必须调用主构造器或其他副构造器。正常的情况下,this()会放在构造器的第一行,此时需要调用父类的构造器,是super()放在第一行还是this()放在第一行呢?
答案:都不行,scala不支持这么做。
多态:父类的引用指向子类的实例。
def main(args: Array[String]): Unit = {
val person:Person=new Student()
}思考一:person.add(1,2) 调用是父类的还是子类的?
def main(args: Array[String]): Unit = {
val person:Person=new Student()
println(person.add(1,2))
}不用想,肯定是子类的,上面的案例中,
Student重写了Person的add方法。所以答案是-1;这个应该知道。
思考二:person.name 是 "坤坤" 还是 "your name?"?
def main(args: Array[String]): Unit = {
val person:Person=new Student()
println(person.name)
}答案是 "坤坤" 在scala 中 属性也具有多态性,这点和java一定要区分开。
回想java 中,对于方法,运行看右(new 的部分),对于属性,运行看左(引用部分)。
public class Demo101 {
public static void main(String[] args) {
A a=new B();
System.out.println(a.name);
a.say();
}
}
class A{
String name="aaaa";
public void say(){
System.out.println("a...");
}
}
class B extends A{
String name="bbbb";
public void say(){
System.out.println("b...");
}
}虽然A和B都有 name属性,但是执行中结果仍然是父类A的name,而方法不一样,需要看new出来最终的对象是什么。 结果:
aaaa
b...这里涉及到了java 中静态分派与动态分派相关的概念
思考三: person.hobby 又是什么?
答案:肯定是 Student 中的 "打篮球";这个我就写,可以下去动手试试。
这就是 scala 中的 三大特性继承、封装、多态;
基本上和java类似,为了区分开的是 java中 属性不具备多态性,scala中属性具备多态性。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。