当前位置: 首页 > news >正文

权威发布疫情最新消息合肥seo报价

权威发布疫情最新消息,合肥seo报价,企业网站制作设,香港有没有做临时工的网站文章目录 类的定义创建类的实例构造函数主构造函数次构造函数init语句块 数据类的定义数据类定义了componentN方法 继承AnyAny:非空类型的根类型Any?:所有类型的根类型 覆盖方法覆盖属性覆盖 抽象类接口:使用interface关键字函数:funUnit:让…

文章目录

    • 类的定义
      • 创建类的实例
      • 构造函数
        • 主构造函数
        • 次构造函数
        • init语句块
    • 数据类的定义
      • 数据类定义了componentN方法
    • 继承
      • Any
        • Any:非空类型的根类型
        • Any?:所有类型的根类型
    • 覆盖
          • 方法覆盖
          • 属性覆盖
    • 抽象类
    • 接口:使用interface关键字
    • 函数:fun
      • Unit:让函数调用皆为表达式
      • 表达式函数体
      • 类头格式化

类的定义

类可以包含:

  • 构造函数和初始化块
  • 函数
  • 属性
  • 嵌套类和内部类
  • 对象声明

你可以将类想象成一个对象的模板,因为它告诉编译器如何创建该特定类的对象。它还将告诉编译器每个对象应该具有哪些属性,并且从该类生成的每个对象都可以
拥有自己独有的属性值。例如,每个Dog对象都有自己的名称、重量和品种属性,每个Dog的属性值都可以是不同的。

class Dog(val name: String, var weight: Int, val breed: String){fun woo() {}
}

如果有参数的话你只需要在类名后面写上它的参数,如果这个类没有任何内容可以省略大括号:

class Dog(val name: String, var weight: Int, val breed: String)

创建类的实例

val myDog = Dog("Fido", 70, "Mixed" )

上面的类有一个默认的构造函数。

注意:创建类的实例不用new

kotlin_class_dog_sample

构造函数

Kotlin中的一个类可以有一个主构造函数和一个或多个次构造函数。

主构造函数

主构造函数是类头的一部分:它跟在类名(和可选的类型参数)后:

class Person constructor(name: String, surname: String) {
}

如果主构造函数没有任何注解或者可见性修饰符,可以省略constructor关键字:

class Person(name: String, surname: String) {
}

主构造函数不能包含任何的代码。初始化的代码可以放到以init关键字作为前缀的初始化块中:

class Person constructor(name: String, surname: String) {init {print("init")}
}

如果构造函数有注解或可见性修饰符,那么constructor关键字是必需的,并且这些修饰符在它前面

次构造函数

类也可以声明前缀有constructor的次构造函数:

class Person{constructor(name: String) {print("name is $name")}
}

如果类有一个主构造函数,每个次构造函数都需要委托给主构造函数(不然会报错), 可以直接委托或者通过别的次构造函数间接委托。
委托到同一个类的另一个构造函数用this关键字即可:

class Person constructor(name: String) {constructor(name: String, surName: String) : this(name) {print( "name is : $name surName is : $surName")}
}
init语句块

Kotlin引入了一种叫作init语句块的语法,它属于上述构造方法的一部分,两者在表现形式上却是分离的。构造方法在类的外部,它只能对参数进行赋值。
如果我们需要在初始化时进行其他的额外操作,那么我们就可以使用init语句块来执行。比如:

class Bird(weight: Double, age: Int, color: String) {init {println("the weight is ${weight}")}
}

当没有val或者var的时候,构造函数的参数可以在init语句块被直接调用。除此之外,不能在其他地方使用。以下是一个错误的用法:

class Bird(weight: Double, age: Int, color: String) {fun printWeight() {print(weight) // Unresolved reference: weight}
}

事实上,我们的构造方法还可以拥有多个init,他们会在对象被创建时按照类中从上到下的顺序先后执行。例如:

class Bird(weight: Double, aget: Int, color: String) {val weight: Doubleval age: Intval color: Stringinit {this.weight = weightthis.age = age}init {this.color = color}
}

可以发现,多个init语句块有利于进一步对初始化的操作进行职能分离,这在复杂的业务开发中显得特别有用。

数据类的定义

数据类通常需要重写equals()hashCode()toString()这几个方法.
但是在Kotlin中你只需要一行代码。

数据类是一种非常强大的类:

使用Kotlin:

data class Artist(var id: Long,var name: String,var url: String,var mbid: String)

数据类自动覆盖它们的equals方法以改变操作符的行为,由此通过检查对象的每个属性值来判断是否相等。
例如,假设你创建了两个属性值完全相同的Artist对象,使用操作符对它们进行比较将返回true,因为它们存放了相同的数据:除了提供从Any父类继承的equals方法的新实现,数据类还覆盖了hashCode和toString方法。

通过数据类,会自动提供以下函数:

  • 所有属性的get() set()方法
  • equals()
  • hashCode()
  • copy()
  • toString()
  • componentN()

如果我们使用不可修改的对象,就像我们之前讲过的,假如我们需要修改这个对象状态,必须要创建一个新的或者多个属性被修改的实例。
这个任务是非常重复且不简洁的。

举个例子,如果要修改Person类中xoliuage:

data class Person(val name: String,val age: Int)
val p1 = Person("xoliu", 19)
val p2 = p1.copy(age = 22)

如上,我们拷贝了对象然后只修改了age的属性而没有修改这个对象的其它状态。

如果你要在Kotlin声明一个数据类,必须满足以下几点条件:

  • 数据类必须拥有一个构造方法,该方法至少包含一个参数,一个没有数据的数据类是没有任何用处的。
  • 与普通的类不同,数据类构造方法的参数强制使用var或者val进行声明
  • data class之前不能用abstract、open、sealed或者inner进行修饰

与任何其他类一样,你可以向数据类添加属性和方法,只需要将它们包含在类主体中。但是有一个大问题,就是在编译器生成数据类的方法实现时,
比如覆盖equals方法和创建copy方法,它仅包含在主构造函数中定义的属性。因此如果你在数据类主体中定义添加的属性,则它们不会被包含到任何编译器生成的方法中。

数据类定义了componentN方法

定义数据类时,编译器会自动向该类添加一组方法,你可以将其作为访问对象属性值的替代方法。它们被称为componentN方法,其中N表示被访问属性的编号(按声明排序)。多声明,也可以理解为变量映射

继承

Kotlin中所有类都有一个共同的超类Any(java是Object),这对于没有超类型声明的类是默认超类:

class Person // 从 Any 隐式继承

Any不是java.lang.Object。它除了equals()hashCode()toString()外没有任何成员。
在Java中,类默认是可以被继承的,除非你主动加final修饰符。而在Kotlin中恰好相反,默认是不可被继承的,除非你主动加可以继承的修饰符open,如果不加open,那它在转化为Java代码时就是final的:

所以Kotlin中所有的类默认都是不可继承的(final)

所以我们只能继承那些明确声明open或者abstract的类:要声明一个显式的超类型,我们把类型放到类头的冒号之后:

open class Person(num: Int)
// 继承
class SuperPerson(num: Int) : Person(num)

冒号后面的Person(num)会调用Person类的构造函数,以确保所有的初始化代码(例如给属性赋值)能够被执行。
调用父类构造函数是强制性的:如果父类有主构造函数,你必须在子类头中调用它,否则代码将无法通过编译。
请记住,即使你没有在父类中显式地添加构造函数,编译器也会在编译代码的时候自动创建一个空构造函数。
假如我们不想为Person类添加构造函数,因此编译器在编译代码的时候创建了一个空构造函数。该构造函数通过使用Person()被调用。

注意: 上面在说到继承的时候class SuperPerson(num: Int) : Person(num)在父类后面必须加上括号,这是为了能够调用到父类的主构造函数。
Kotlin中规定,当一个类既有主构造函数又有次构造函数时,所有的次构造函数都必须调用主构造函数(包括间接调用)
但是如果类没有主构造函数,那么每个次构造函数必须使用super关键字初始化其基类型,或委托给另一个构造函数做到这一点。 这里很特殊,在Kotlin
中是允许类中只有次构造函数,没有主构造函数的。当一个类没有显式的定义主构造函数且定义了次构造函数时,它就是没有主构造函数的。

如果该类有一个主构造函数,其基类必须用基类型的主构造函数参数就地初始化。

如果类没有主构造函数,那么每个次构造函数必须使用super关键字初始化其基类型,或委托给另一个构造函数做到这一点。
注意,在这种情况下,不同的次构造函数可以调用基类型的不同的构造函数:

class MyView : View {constructor(ctx: Context) : super(ctx)constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs)
}

也就是MyView类的后面没有显式的定义主构造函数,同时又定义了次构造函数。所以现在MyView类是没有主构造函数的。那么既然没有主构造函数,继承View类
的时候也就不需要再在View类后加上括号了。

另外,由于没有主构造函数,次构造函数只能直接调用父类的构造函数,上述代码也是将this关键字换成了super关键字,这部分就很好理解了。

Any

我们都知道,Java并不能在真正意义上被称为一门"纯面向对象"语言,因为它的原始类型(如int)的值与函数等并不能被视作对象。

但是Kotlin不同,在Kotlin的类型系统中,并不区分原始类型(基本数据类型)和包装类型,我们使用的始终是同一个类型。

Any:非空类型的根类型

与Object作为Java类层级结构的顶层类似,Any类型是Kotlin中所有非空类型(如String、Int)的超类,如:

与Java不同的是,Kotlin不区分"原始类型"(primitive type)和其他的类型,他们都是同一类型层级结构的一部分。 如果定义了一个没有指定父类型的类型,
则该类型将是Any的直接子类型。如:

class Animal(val weight: Double)
Any?:所有类型的根类型

如果说Any是所有非空类型的根类型,那么Any?才是所有类型(可空和非空类型)的根类型。这也就是说?Any?是?Any的父类型。

覆盖

方法覆盖

只能重写显示标注可覆盖的方法:

open class Person(num: Int) {open fun changeName(name: String) {}fun changeAge(age: Int) {}
}class SuperPerson(num: Int) : Person(num) {override fun changeName(name: String) {// 通过super关键字调用超类实现super.changeName(name)}
}

SuperPerson.changeName()方法前面必须加上override标注,不然编译器将会报错。如果像上面Person.changeAge()方法没有标注open,则子类中不能定义相同的方法: (不能重写,但能重载)

class SuperPerson(num: Int) : Person(num) {override fun changeName(name: String) {super.changeName(name)}// 编译器报错fun changeAge(age: Int) {}// 重载是可以的fun changeAge(name: String) {}// 重载是可以的fun changeAge(age: Int, name: String) {}
}

标记为override的成员本身是开放的,也就是说,它可以在子类中覆盖。如果你想禁止再次覆盖,可以使用final关键字:

open class SuperPerson(num: Int) : Person(num) {final override fun changeName(name: String) {super.changeName(name)}
}
属性覆盖

属性覆盖与方法覆盖类似,只能覆盖显式标明open的属性,并且要用override开头:

open class Person(num: Int) {open val name: String = ""open fun changeName(name: String) {}fun changeAge(age: Int) {}
}open class SuperPerson(num: Int) : Person(num) {override val name: Stringget() = super.namefinal override fun changeName(name: String) {super.changeName(name)}}

每个声明的属性可以由具有初始化器的属性或者具有get方法的属性覆盖,如果某个属性在父类中被定义为val,你可以在子类中使用var属性覆盖它。
只需要覆盖该属性并将其声明为var即可。请注意,这只适用于这一种方式。如果尝试使用val覆盖var属性,编译器将会报错

抽象类

类和其中的某些成员可以声明为abstract。抽象成员在本类中可以不用实现。需要注意的是,我们并不需要用open标注一个抽象类或者函数——因为这不言而喻,这些属性一定需要去实现的

我们可以用一个抽象成员覆盖一个非抽象的开放成员:

open class Base {open fun f() {}
}abstract class Derived : Base() {override abstract fun f()
}

接口:使用interface关键字

接口可以让你在父类层次结构之外定义共同的行为,接口用于为共同行为定义协议,使你可以不依赖严格的继承结构却又可以利用多态。与抽象类类似,接口不能被实例化且可以定义抽象或具体的方法和属性,但两者有一个关键的不同点:类可以实现多个接口,但是只能继承于一个直接父类。所以接口不仅拥有抽象类的优点,而且使用起来更加灵活。

interface FlyingAnimal {fun fly()
}

虽然Kotlin接口支持属性声明,然而它在Java源码中是通过一个get方法来实现的。在接口的属性并不能像Java接口那样,被直接赋值一个常量。如以下这样是错误的:

interface Flyer {val height = 1000 // error Property initializers are not allowed in interfacesval speed: Int// 可以支持默认实现方法,反编译可以看到是通过静态内部类来提供fly方法的默认实现的,Java8也开始支持了接口方法的默认实现fun fly() {println("I can fly")}
}

Kotlin提供了另外一种方式来实现这种效果:

interface Flyer {val height get() = 1000
}

一个类实现接口时:

class Bird() : Flyer {//  ...
}

接口的后面不用加上括号,因为它没有构造函数可以去调用。

函数:fun

fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)
}

如果你没有指定它的返回值,它就会返回UnitUnitJava中的void类似,但是Unit是一个类型,而void只是一个关键字。Unit可以省略。

fun maxOf(a: Int, b: Int): Int {if (a > b) {return a} else {return b}
}

Unit:让函数调用皆为表达式

如果函数返回Unit类型,该返回类型应该省略:

fun foo() { // 省略了 ": Unit"}

之所以不能说Java中的函数调用皆是表达式,是因为存在特例void。众所周知,在Java中如果声明的函数没有返回值,那么它就需要用void来修饰,如:

void foo() {System.out.println("return nothing")
}

所以foo()就不具有值和类型信息,它就不能算作一个表达式。在Kotlin中,函数在所有的情况下都具有返回类型,所以他们引入了Unit来替代Java中的void关键字。

Unit与Int一样,都是一种类型,然而它不代表任何信息,用面向对象的术语来描述就是一个单例,它的实例只有一个,可写为()。

表达式函数体

如果返回的结果可以使用一个表达式计算出来,你可以不使用括号而是使用等号:

fun add(x: Int,y: Int) : Int = x + y // 省略了{}

Kotlin支持这种单行表达式与等号的语法来定义函数,叫做表达式函数体,作为区分,普通的函数声明则可以叫做代码块函数体。如你所见,在使用表达式函数体
的情况下我们可以不声明返回值类型,这进一步简化了语法。

我们可以给参数指定一个默认值使的它们变的可选,这是非常有帮助的。这里有一个例子,在Activity中创建了一个函数用来Toast一段信息:

fun toast(message: String, length: Int = Toast.LENGTH_SHORT) {Toast.makeText(this, message, length).show()
}

上面代码中第二个参数length指定了一个默认值。这意味着你调用的时候可以传入第二个值或者不传,这样可以避免你需要的重载函数:

toast("Hello")
toast("Hello", Toast.LENGTH_LONG)

类头格式化

有少数几个参数的类可以写成一行:

class Person(id: Int, name: String)

具有较长类头的类应该格式化,以使每个主构造函数参数位于带有缩进的单独一行中。此外,右括号应该另起一行。如果我们使用继承,
那么超类构造函数调用或者实现接口列表应位于与括号相同的行上:

class Person(id: Int, name: String,surname: String
) : Human(id, name) {// ……
}

对于多个接口,应首先放置超类构造函数调用,然后每个接口应位于不同的行中:

class Person(id: Int, name: String,surname: String
) : Human(id, name),KotlinMaker {// ……
}
http://www.mnyf.cn/news/52071.html

相关文章:

  • 广西北海联友建设网站管理武汉网络推广seo
  • shopify可以用来做B2B网站吗域名停靠网页推广大全2023
  • 爬虫wordpress潍坊seo教程
  • qq是谁的公司开发的企业网站关键词优化
  • 域名解析查询方法关于进一步优化落实疫情防控措施
  • 网络班级网站建设北京seo实战培训班
  • 怎么修改wordpress模板文件seo在线优化工具
  • 个人备案的网站可以做什么企业网站推广渠道
  • 短租网站那家做的好处电商关键词seo排名
  • 广东网站建设系统武汉竞价托管公司
  • 网站后台数据应该怎么做网络推广外包要多少钱
  • 哪里有做网站设计seo快排优化
  • 太原网站推广怎么做北京百度推广客服电话多少
  • 徐州网站制作机构快速排名推荐
  • 做网站的公司有哪些网店推广的方式
  • 多元 集团 网站建设方案深圳推广
  • 如何在wordpress首页显示文章列表网站优化的主要内容
  • 医疗生物科技 网站建设seo的中文含义是
  • 音乐中文网站模板营销策略案例
  • 广西南宁市网站建设服务中心济南做网站公司哪家好
  • 如何做网站解析今日国际新闻热点
  • 怎么样做销往非洲太阳能板的网站网络精准推广
  • 35互联做网站seo怎么赚钱
  • 河南省建设厅网网站首页武汉seo首页优化技巧
  • 个人网站怎么做代码品牌营销网站建设
  • 网站建设案例代理商杭州seo搜索引擎优化公司
  • 广东建设注册执业中心网站中国网评中国网评
  • 网网站制作开发百度seo流量
  • 制作一个静态网站的步骤自己怎么做网址
  • 金华住房和城乡建设厅网站比较火的推广软件