当前位置:网站首页>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函数
边栏推荐
- After MySQL 8 OCP (1z0-908), hand in your homework
- Problems caused by slivereappbar
- 12306 ticket system crawling - 1. Saving and reading of city code data
- 【FreeSwitch开发实践】使用SIP客户端Yate连接FreeSwitch进行VoIP通话
- CV learning notes (optical flow)
- Lesson 3: gcc compiler
- Solve the problem of C # calling form controls across threads
- 利用模m的原根存在性判断以及求解
- QT note 2
- 【FreeSwitch开发实践】自定义模块创建与使用
猜你喜欢

Nodejs2day(nodejs的模块化,npm下载包,模块加载机制)

I am 35 years old.

基于Raft共识协议的KV数据库

22-07-16 personal training match 3 competition experience

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

Prefix infix suffix expression (written conversion)

Solve the problem of C # calling form controls across threads

Using the primitive root of module m to judge and solve

Leetcode and query question summary

22-07-14 personal training match 2 competition experience
随机推荐
基于C语言设计的换乘指南打印系统
Nodejs2day(nodejs的模块化,npm下载包,模块加载机制)
C#入门系列(三十一) -- 运算符重载
Using the primitive root of module m to judge and solve
File management file system based on C #
Uninstallation of dual systems
OSPF summary
Transfer guide printing system based on C language design
CV learning notes (optical flow)
Fluent uses protobuf
Flutter WebView three fingers rush or freeze the screen
Please tell me if there is any way to increase the write out rate when the Flink SQL client is in the sink table. When synchronizing through sink table
Oracle 19C OCP certification examination software list
23.8 using the applicationrunner or commandlinerunner to implement applicationrunner and commandlinerunner
P1825 [USACO11OPEN]Corn Maze S
各位老师,请问在flinkcdc中,sqlserver如何获取到ddl?
2022-7-6 personal qualifying 3 competition experience
利用模m的原根存在性判断以及求解
Foundry tutorial: writing scalable smart contracts in various ways (Part 1)
Memory management - dynamic partition allocation simulation


