当前位置:网站首页>Kotlin属性与字段
Kotlin属性与字段
2022-07-26 08:37:00 【尘心平】
目录
属性的声明
在主构造函数中声明
在主构造函数中采用 var/val 变量:类型 即可声明属性
open class A(var name:String,var node:String){ override fun toString(): String { return "A(name='$name', node='$node')" //name,node即属性 } } fun main(args:Array<String>){ var a=A("Hellen","1") println(a) //A(name='Hellen', node='1') }
在属性初始化器中声明
具体格式为:
var/val 属性名 [ : 属性类型 ] [ =值 ]
[ 访问权限符 set()=/set(){} ]
[ 访问权限符 get()=/get(){} ]
其中 [ ] 内为可选部分,var变量有get和set方法,而val变量只有get方法
当属性类型可以由set和get推断出时,属性类型可省略,但val只有get方法,必须声明类型
一般指定值,就可省略属性类型
var count=1 open class A{ var name:String //有了默认get,自定义了set和构造函数,值省略 private set(value){ field=value println("set name's value") } val node:Int get() { return count++ }//只有get默认,值不能省略。可指定值,省去类型 constructor(name:String){ this.name=name } override fun toString(): String { return "A(name='$name', node=$node)" } } fun main(args:Array<String>){ var a=A("Hellen") //set name's value var b=A("Peter") //set name's value var c=A("John") //set name's value println(a) //A(name='Hellen', node=1) println(b) //A(name='Peter', node=2) println(c) //A(name='John', node=3) }
属性的使用
一般属性在类中可直接用属性名访问,有名称冲突时可以使用this.属性名;在类外可以通过 对象.属性名 访问public属性
var count=1 open class A{ var name:String set(value) { field=value println("name's set") } val node get() = count++ var kotlin_score:Int val kotlin_level:String get() { println("kotlin_level's get") return when(kotlin_score/10){ 9,10->{ "A" } 8->{ "B" } 6,7->{ "C" } else->{ "D" } } } constructor(name:String,kotlin_score:Int){ this.name=name //名称冲突,用this.属性名访问 this.kotlin_score=kotlin_score //名称冲突,用this.属性名访问 //this.属性名=变量/值,默认调用属性名的set函数 } override fun toString(): String { //无名称冲突,直接用属性名访问 return "A(name='$name', node=$node, kotlin_score=$kotlin_score, kotlin_level='$kotlin_level')" //$属性名,会默认调用属性名的get函数 print(属性名)等需要属性名值的地方都是默认调用了属性名的get函数 } } fun main(args:Array<String>){ var a=A("Hellen",85) //name's set var b=A("Peter",100) //name's set var c=A("John",67) //name's set println(a) //kotlin_level's get //A(name='Hellen', node=1, kotlin_score=85, kotlin_level='B') println(b) //kotlin_level's get //A(name='Peter', node=2, kotlin_score=100, kotlin_level='A') println(c) //kotlin_level's get //A(name='John', node=3, kotlin_score=67, kotlin_level='C') println(c.name+" "+c.kotlin_score)// 类外可调用对象的public属性,对象.属性名 }
幕后字段
幕后字段主要是解决属性的set函数调用赋值时的内存溢出问题,主要用于让一个属性在不同的条件下有不同的值
一般按照Java的理解,set函数会写成如下这样的形式
var name:String set(value) { this.name=value }这样写IDEA会报黄,显示未分配setter
这样运行以后也会出现报错:栈溢出StackOverflowError
将Kotlin类转换为Java如下,可见有setName循环调用
public class A { @NotNull private String name; @NotNull public final String getName() { return this.name; } public final void setName(@NotNull String value) { Intrinsics.checkNotNullParameter(value, "value"); this.setName(value);//循环调用 } @NotNull public String toString() { return "A(name='" + this.name + "')"; } public A(@NotNull String name) { Intrinsics.checkNotNullParameter(name, "name"); super(); this.setName(name); } }因此为了解决这个问题,就引出了幕后字段:在Kotlin中, 如果属性至少一个访问器使用默认实现,那么Kotlin会自动提供幕后字段。幕后字段用关键字field表示,指代当前的属性,只能用于get和set函数中,也因此,set函数写作如下:
var name:String set(value) { field=value //field指代属性name }注意:并不是所有的Kotlin属性都有幕后字段:要满足以下两种情况之一:set和get其中之一采用默认实现;自定义的set和get中使用field
幕后属性
幕后属性满足:对类外只可读,但在类内既可读又可写
实现幕后属性需要两个变量的声明:
(官方这样要求,但应该可以通过声明var属性但是自定义 public get,private set 实现幕后属性的特点,只是反编译的Java代码不同)
private var a: Int=0 public val m_a: Int get() = a //a即为幕后属性 //反编译为: //public class A { // private int a; // // public final int getM_a() { // return this.a; // } //}var a:Int=0 private set(value){ field=value }//get默认public //反编译为 //public class A { // private int a; // // public final int getA() { // return this.a; // } // // private final void setA(int value) { // this.a = value; // } //} // 较官方使用,多反编译了set函数
边栏推荐
- Dear teachers, how can sqlserver get DDL in flinkcdc?
- [freeswitch development practice] use SIP client Yate to connect freeswitch for VoIP calls
- Registration of finite element learning knowledge points
- 各位老师,请问在flinkcdc中,sqlserver如何获取到ddl?
- B title: razlika priority queue approach
- 1、 Redis data structure
- 23.9 application exit application exit
- [GUI] GUI programming; AWT package (interface properties, layout management, event monitoring)
- Flutter compilation fails
- Error handling response: Error: Syntax error, unrecognized expression: .c-container /deep/ .c-contai
猜你喜欢

C#入门系列(三十一) -- 运算符重载

Pxe原理和概念

Nodejs2day (modularization of nodejs, NPM download package, module loading mechanism)

Shell programming

22-07-16 personal training match 3 competition experience

2022-7-9 personal qualifying 6 competition experience
![[freeswitch development practice] use SIP client Yate to connect freeswitch for VoIP calls](/img/8b/d5792a00fc5798d3d960f1f1b1088e.png)
[freeswitch development practice] use SIP client Yate to connect freeswitch for VoIP calls

OA项目之我的会议(查询)

Registration of finite element learning knowledge points

Guitar staff link Jasmine
随机推荐
Memory management based on C language - Simulation of dynamic partition allocation
Excel find duplicate lines
Kotlin中room数据库的使用
QSS add resource file of QT
Inaccurate problem of flutter fijkplayer seekto
Oracle 19C OCP 1z0-082 certification examination question bank (42-50)
Write common API tools swagger and redoc
Storage of drawings (refined version)
When developing flutter, idea_ ID cannot solve the problem
Take out brother is the biggest support in this society
Flutter distribution
[time complexity, space complexity]
Flutter compilation fails
If Yi Lijing spits about programmers
MySQL 8.0 OCP 1z0-908 certification examination question bank 1
Sub Chocolate & paint area
【C语言】程序员筑基功法——《函数栈帧的创建与销毁》
Alphabetic string
Grid segmentation
Memory management - dynamic partition allocation simulation


