ScalaNote05-类、属性、方法

网友投稿 672 2022-09-02

ScalaNote05-类、属性、方法

ScalaNote05-类、属性、方法

通俗定义

**看一个实际案例:**张老太养了只猫猫:一只名字叫小白,今年3岁,白色。还有一只叫小花,今年10岁,花色。请编写一个程序,当用户输入小猫的名字时,就显示该猫的名字,年龄,颜色。如果用户输入的小猫名错误,则显示 张老太没有这只猫猫。

类:

管理多个不同类型的数据-[属性](如猫名字、年龄、颜色)对属性进行操作-[方法](如猫可以run、cry等等)

类是抽象的,概念的,代表一类事物,比如人类,猫类…对象是具体的,实际的,代表一个具体事物,如上面案例中的小花、小白。类是对象的模板,对象是类的一个个体,对应一个实例。

Scala定义类

在Scala中,我们可以这样定义一个类

class 类名 { 类体}

属性

类体中定义类的属性和类的方法,其中类的属性可以为值数据类型,也可是引用类型,比如cat类的age属性。

属性的定义语法同变量,示例:[访问修饰符] var 属性名称 [:类型] = 属性值

class cat{ val name:String = "" var age:Int=0 private var color:String="white" var color2 = "color1="+color}

defined class cat

以上面的cat类为例:定义了name、age、color三个属性,其中color为私有属性,对象中不可以引用,只能在类内部访问。如果需要一个只读属性,可以用val。

val catx = new cat()

catx: cat = cat@1aa638ff

catx.age =2

catx.age: Int = 2

catx.name

res56: String = ""

catx.name ="Name can not change"

:26: error: reassignment to val catx.name ="Name can not change" ^

上面报错,name只能访问,不可修改

catx.color2

res57: String = color1=white

catx.color

:28: error: variable color in class cat cannot be accessed in cat catx.color ^

class Person { var age : Int = 10 var sal = 8090.9 //给属性赋初值,省略类型,会自动推导 var Name = null // Name 是什么类型? null类型 var address : String = null // address还是string var hiscat = new cat()}

defined class Person

也可以不指定属性值,而用"_"代替。如下所示:

class Dog{ var name:String=_ //默认null var age:Int=_ //默认0 var isDog:Boolean=_ //默认false var eatamount:Float=_ //默认0.0}

defined class Dog

val puppy = new Dog()

puppy: Dog = Dog@10e68ad8

println("puppy.name="+puppy.name+"\n" +"puppy.age="+puppy.age+"\n" +"puppy.isDog="+puppy.isDog+"\n" +"puppy.eatamount="+puppy.eatamount)

puppy.name=nullpuppy.age=0puppy.isDog=falsepuppy.eatamount=0.0

对象

什么是对象,引用下菜鸟教程:类是对象的抽象,而对象是类的具体实例。类是抽象的,不占用内存,而对象是具体的,占用存储空间。类是用于创建对象的蓝图,它是一个定义包括在特定类型的对象中的方法和变量的软件模板。

在scala中创建对象的语法如下:

val | var 对象名 [:类型] = new 类型()

对于第一点,一般情况下使用val即可,第2点则需要注意,如下例,Child是Person子类,如果通过new Child()新建一个对象leo,并且希望类型为Person则必须指定类型为Person,否则默认为Child。这个用法有点儿骚气~

class Person{ var name="jack"}class Child extends Person{ var age=6}

defined class Persondefined class Child

val leo1 = new Child()val leo2:Person = new Child()

leo1: Child = Child@44f3c0dleo2: Person = Child@250716e

leo1.getClass

res6: Class[_ <: Child] = class Child

leo2.getClass

res5: Class[_ <: Person] = class Child

对象访问属性很简单,​​对象.属性​​即可

leo1.age

res7: Int = 6

leo2.age

:28: error: value age is not a member of Person leo2.age ^

类和对象的内存分配机制

类和对象的内存分配机制,可以通过一张图了解:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5pTZDPaB-1582286688619)(…/Picture/pic02.png)]

即新建一个对象p1,再将p1赋给p2,此时两个变量都指向同一个对象,其实有点像python的浅copy,如果其中有个值发生变化,两者都变。看一个例子:

class Dog{ var name = "jack"}val p1 = new Dog()var p2 = p1println("p1.name="+p1.name+"\n"+"p2.name="+p2.name)p2.name = "john"println("p1.name="+p1.name+"\n"+"p2.name="+p2.name)

p1.name=jackp2.name=jackp1.name=johnp2.name=johndefined class Dogp1: Dog = Dog@ed3b2ffp2: Dog = Dog@ed3b2ffp2.name: String = john

方法

方法和函数定义差不多,我自己理解,方法就是一个对象的函数。看个例子方便理解

class Dog{ var name = "jack" def bark(name:String){ println("I am "+name+"\n"+"I can wangwangwang") }}val p1 = new Dog()p1.bark(p1.name)

I am jackI can wangwangwangdefined class Dogp1: Dog = Dog@3b70573a

这里定义了bark的方法,对象调用这个方法是把名字传进去即可。

构造器

在上例中,如果我们在new Dog时就初始化一个name属性,该怎么处理呢?这里可以使用构造器(constructor),又叫构造方法,它是类的一种特殊的方法,它的主要作用是完成对新对象的初始化。

主构造器

构造器又分为主构造器和辅助构造器,主构造器是通过类名后面跟的括号里加参数列表来定义,辅助构造器是通过关键字this定义。

class 类名(形参列表) { // 主构造器 // 类体 def this(形参列表) { // 辅助构造器 } def this(形参列表) { //辅助构造器可以有多个... }}

class Student(inName:String="jfdja",inAge:Int){ val name = inName val age = inAge println("Name = "+inName+ "; Age = "+age)} val student1 = new Student("Jacky",19)val student2 = new Student(inAge=18,inName="Jack")val student3 = new Student(inAge=20)

Name = Jacky; Age = 19Name = Jack; Age = 18Name = jfdja; Age = 20defined class Studentstudent1: Student = Student@2b6f5b1bstudent2: Student = Student@370d1fffstudent3: Student = Student@34bbfa45

主构造器会执行类定义中的所有语句,当我们没有指定参数名时,按照从左往右顺序赋值,如果变量类型不一致会报错。也可以带上参数名,此时顺序可不一致。这样看,类的参数初始化和函数参数赋值好像也差不多,参数也可以有默认值,这样是不规范?

辅助构造器

辅助构造器有些细节我自己也没有搞清楚,简单记录下韩老师讲的内容吧。   辅助构造器名称为this,多个辅助构造器通过不同参数列表进行区分,比如参数的个数不一样或者参数的类型一致。

下面的内容不保证正确,代码是能跑通。看下面代码,如果使用辅助构造器,则在辅助构造器的第一行需要调用主构造器

这里把主构造器的两个参数也放到辅助构造器里了,第一行直接调用this(inName,inAge)如果辅助构造器参数不包含inName,inAge,则需要this(“jacky”,10)这样调用

class Person(inName: String, inAge: Int) { var name: String = inName var age: Int = inAge age += 10 println("Main constructor \n"+"name =" +name+"\n"+"age =" +age) def this(inName: String, inAge: Int,name: String) { this(inName,inAge) this.name = name println("Auxiliary constructor \n"+"name =" +name+"\n"+"age =" +age) } def showInfo(): Unit = { println("Person Info:") println("name=" + this.name) println("age=" + this.age) }}

defined class Person

val eve = new Person("abc",20,"cba")

Main constructor name =abcage =30Auxiliary constructor name =cbaage =30eve: Person = Person@577b4310

从代码执行顺序上可以看出:

传入了(“abc”,20,“cba”),根据参数个数和参数类型,调用辅助构造器辅助构造器第一行调用主构造器,因此完成print操作之后在执行辅助构造器里面的代码,对name重赋值,并且print

class Person(inName: String, inAge: Int) { var name: String = inName var age: Int = inAge age += 10 println("Main constructor \n"+"name =" +name+"\n"+"age =" +age) def this(name: String) { this("inName",10) this.name = name println("Auxiliary constructor \n"+"name =" +name+"\n"+"age =" +age) } def showInfo(): Unit = { println("Person Info:") println("name=" + this.name) println("age=" + this.age) }}

defined class Person

new Person("abc")

Main constructor name =inNameage =20Auxiliary constructor name =abcage =20res5: Person = Person@69af6740

再看一个特殊的case:

class B{ println("B--->")}class A extends B{ println("A--->") def this(name:String){ this println("A NAME = "+name) }}new Aprintln("--------lines--------")new A("AA")

B--->A--->--------lines--------B--->A--->A NAME = AAdefined class Bdefined class Ares8: A = A@18572a9c

上面的code可以看到,当A继承B时,新建A类对象时:

先调用父类的主构造器,输出"B—>"再调用A的主构造器,输出"A—>"最后执行辅助构造器中的println("A NAME = "+name)

属性的高级部分

这部分涉及下面三个点:

class Boy(inName:String,val inAge:Int,var inSex:String){ //println("Love U,Simple") def showInfo(){ println("Boy Info:") println("name=" + inName) println("age=" + inAge) println("inSex=" + inSex) }}val x = new Boy("jack",16,"male")x.inSex ="female"x.showInfo()

Love U,SimpleBoy Info:name=jackage=16inSex=femaledefined class Boyx: Boy = Boy@5ed73402x.inSex: String = female

结合上面的代码,即:

主构造器里的var inSex可以被修改而val inAge 可读不可写但是这俩都编程了对象的属性

Bean属性

JavaBeans规范定义了Java的属性是像getXxx()和setXxx()的方法。许多Java工具(框架)都依赖这个命名习惯。为了Java的互操作性。将Scala字段加@BeanProperty时,这样会自动生成规范的 setXxx/getXxx 方法。这时可以使用 对象.setXxx() 和 对象.getXxx() 来调用属性。   注意:给某个属性加入@BeanPropetry注解后,会生成getXXX和setXXX的方法并且对原来底层自动生成类似xxx(),xxx_$eq()方法,没有冲突,二者可以共存。

java的东西我不懂,直接看个例子吧

import scala.beans.BeanPropertyclass Car { @BeanProperty var brand: String = "Audi"}val x = new Car()println("x.name = "+x.brand)println("x.getBrand = "+x.getBrand)x.setBrand("Mercedes Benz")println("x.getBrand = "+x.getBrand)

x.name = Audix.getBrand = Audix.getBrand = Mercedes Benzimport scala.beans.BeanPropertydefined class Carx: Car = Car@34febf56

稀里糊涂地看了一天了,没有java基础学scala还挺费劲~Whatever,还是要好好学习!

2020-02-21 于南京市栖霞区

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:数据库读写分离提高性能详解,原理是什么(数据库使用读写分离的主要目的是什么)
下一篇:运维:Ccentos8安装supervisor守护Nginx进程笔记
相关文章

 发表评论

暂时没有评论,来抢沙发吧~