[修饰符] class 类名{
类体
}
class Student {
}
2.属性1.scala语法中,类并不声明为public,所有这些类都具有公有可见性(默认就是public)
2.一个scala源文件可以包含多个类,而且默认都是public
class Student {
var name:String = _
var age:Int = 0
def show(): Unit ={
println(s"$name,$age")
}
}
1.属性的定义语法同变量 [访问修饰符] var 属性名 [:类型] = 属性值
2.属性的定义类型可以为任意类型, 包含值类型或者引用类型
3.scala中声明一个属性,必须显示的初始化,然后根据初始化数据的类型自动推断,属性类型可以省略
4.如果赋值为null,则一定要加类型,因为不加类型,那么该属性的类型就是Null类型
5.如果在定义属性时,暂时不赋值,也可以使用符号_,由系统分配默认值、
| 类型 | _ 对应的值 |
|---|---|
| Byte、Short、Int、Long | 0 |
| Float、Double | 0.0 |
| String和引用类型 | null |
| Boolean | false |
给某个属性加入@BeanProperty注解后,会生成getXXX和setXXX方法 [了解]
class Student (@BeanProperty name:String){
@BeanProperty
var age:Int = _
...
}
3.创建对象val|var 对象名[:类型] = new 类型() val student:Student= new Student()
4.方法1.如果我们不希望改变对象的引用(内存地址),应该声明为val性质的,否则声明为var,scala设计者推荐使用val,因为一般来说,在程序中,我们只是改变对象属性的值,而不是改变对象的引用
2.scala在声明对象变量时,可以根据创建对象的类型自动推断,所以类型声明可以省略,但当类型和后边new对象类型有继承关系即多态时,就必须写了
scala中的方法其实就是函数
语法
def 方法名(参数列表)[:返回值类型] = {
方法体
}
//在Student类中定义方法
def show(): Unit ={
println(s"$name,$age")
}
5.构造器
和java一样,scala构造对象也需要调用构造方法,并且可以有任意多个构造方法(即scala中构造器也支持重载)
scala类的构造器包括:主构造器 和 辅助构造器
class 类名(形参列表){ //主构造器
def this(形参列表){ //辅助构造器
}
def this(形参列表){ //辅助构造器可以有多个
}
}
class Student(name2:String){
var name:String = name2
var age:Int = 0
def this(name:String,age:Int){
this(name) // 辅助构造器必须在第一行显示调用主构造器(可以是直接,也可以是间接)
this.age = age
}
def show(): Unit ={
println(s"$name,$age")
}
}
-
如果主构造器无参数,小括号可以省略,构建对象时调用的构造方法的小括号也可省略
class Student{ } val s = new Student -
主构造器会执行类定义中的所有语句
class Student{ println("啦啦啦啦~~~") } val s = new Student //控制台打印 啦啦啦啦~~~ -
如果想让主构造器变成私有的,可以在()之前加上private,这样用户只能通过辅助构造器来构造对象了
class Student private(){} -
主构造形参修饰
scala类的主构造器的形参未用任何修饰符修饰,那么这个参数是局部变量. 如果参数使用val关键字声明,那么scala会将参数作为类的私有的只读属性使用 如果参数使用var关键字声明,那么scala会将参数作为类的成员属性使用,并会提供属性对应的 xxx()[类似于getter]/xxx_$eq()[类似setter]方法,即这时的成员属性是私有的,但是可读性 class Student (var name:String){ var age:Int = _ def this(name:String,age:Int){ this(name) this.age = age } def show(): Unit ={ println(s"$name,$age") } }
//使用private 修饰属性后,生成的setter/getter方法也是private
private var age:Int = _
//声明age属性的set和get方法
def setAge(age:Int):Unit={
if(age > 0 && age < 100){
this.age = age
}
}
def getAge(): Int ={
return age
}
2.继承
-
继承父类语法
class 子类名 extends 父类名{ 类体 } -
重写父类方法
重写父类方法需要使用override修饰 override def xxx(): Unit ={ }
多态 1.父类引用指向子类对象(实例)
var a:Animal = new Cat() //var a:Cat = new Cat()
2.多态的特点
//a对象只能调用父类继承的方法(如果重写,则执行子类方法)
var a:Animal = new Cat()
// var a:Cat = new Cat() 非多态的方式,对象可以调用子类所有方法(继承的+特有的)
3. 多态的应用场景 [兼容性、扩展性]
参数和返回值
1.父类类型作为形参,调用该方法时可以传递任意该父类的任意子类对象
例如 : test1(a:Animal)
2.返回值类型写成父类类型,该方法可以返回该父类的任意子类对象
例如 : 工厂设计模式
4. 通过多态创建的对象,如果希望调用子类特有的方法,需要进行类型转换
java
Animal a = test2()
if(a instanceof Cat){
Cat c = (Cat)a;
}
scala
要测试某个对象是否属于某个给定的类,可以用isInstanceOf方法。
用asInstanceOf方法将引用转换为子类的引用
var s:Person = new Student
if(s.isInstanceOf[Student]){
val student: Student = s.asInstanceOf[Student]
student.study()
}
八、抽象类
在scala中,通过abstract关键字标记不能被实例化的类。方法不用标记abstract,只要省掉方法体即可
abstract class Person{
var name:String = _
def sayHello()
//def sayHello():Unit = ???
}
九、接口 trait
-
声明一个特质 trait
trait 特质名{ trait 体 } -
使用特质
1) 没有父类,可以直接继承特质 class 类名 extends 特质1 with 特质2 2) 有父类 class 类名 extends 父类 with 特质1 with 特质2 trait A{ def test1() } trait B{ def test2() } class C extends A with B{ override def test1(): Unit = { println("覆盖特质A的test1方法") } override def test2(): Unit = { println("覆盖特质B的test2方法") } }
因为Scala运行在Java8之上,所以特质中方法可以有默认实现
- 动态混入
abstract class Animal{
def eat()
}
trait Speakable{
def speak()
}
trait Flyable{
def fly()
}
class Pig extends Animal with Speakable{
var name:String = _
def this(name:String){
this()
this.name = name
}
override def eat(): Unit = {
println(s"${name} 吃东西")
}
override def speak(): Unit = {
println(s"${name} 哼哼")
}
}
object Test2_trait {
def main(args: Array[String]): Unit = {
val pig = new Pig("佩奇")
pig.eat()
pig.speak()
val pig2 = new Pig("猪八戒") with Flyable{
override def fly(): Unit = {
println(s"${name}飞起来!!")
}
}
pig2.eat()
pig2.speak()
pig2.fly()
}
}
十、静态属性和静态方法
介绍:由于Scala没有静态方法,通过object去定义静态方法或者静态对象。
单例类单例类使用object修饰,所有声明在object中的方法都是静态方法,类似于Java中声明的工具类的作用。
//object中的方法都是静态方法 class中的方法都是非静态方法
//object中的主函数才能正常运行
object SingleObject {
def sum(x:Int,y:Int):Int={
x+y
}
}
var so1=SingleObject var so2=SingleObject println(so1==so2) //true SingleObject.sum(1,2)伴生对象
如果类和object在一个scala文件中,则称为object User 是class User的伴生对象
class User{
}
//Scala中伴生对象采用object关键字声明,伴生对象中的全是”静态“内容,可以通过伴生对象名称直接调用
//伴生对象对应的类称之为伴生类,伴生对象的名称应该和伴生类名一致
//伴生对象中的属性和方法都可以通过伴生对象(类名)直接调用访问
//从语法角度来讲,所谓的伴生对象其实就是类的静态方法和成员的集合
object User{ //伴生对象
}
伴生对象 apply方法
使用伴生对象可以方便的创建对象,只需要覆盖对应的apply方法,如下:
class User {
def test2(): Unit ={
println("test2方法execute")
}
}
object User{
def apply(): User = {
println("11111111")
new User()
}
}
测试:
val user = User() //或者 val user = User.apply()
user.test2()
十一、隐式传值和隐式转换
1.隐式函数
def main(args: Array[String]): Unit = {
implicit def f1(d:Double):Int = {
d.toInt
}
val num:Int = 3.5
println(num)
}
2.隐式变量
def main(args: Array[String]): Unit = {
implicit var name:String = "tom"
def hello(implicit name:String): Unit ={
println(name + " say hello")
}
hello
}
3.隐式类隐式变量的优先级高于默认值
object Demo3 {
def main(args: Array[String]): Unit = {
implicit class A(val b:B){
def test2(): Unit ={
println("test2方法执行了")
}
}
var b = new B
b.test2()
}
}
class B{
def test1(): Unit ={
println("test1方法执行了")
}
}
十二、异常
Scala提供try和catch块来处理异常。try块用于包含可疑代码。catch块用于处理try块中发生的异常。可以根据需要在程序中有任意数量的try…catch块。
语法处理上和Java类似,但是又不尽相同。
// Scala
try {
val r = 10 / 0
} catch {
case ex: ArithmeticException=> println("捕获了除数为零的算数异常")
case ex: Exception => println("捕获了异常")
} finally {
// 最终要执行的代码
}
Scala的异常的工作机制和Java一样,但是Scala没有“checked”异常,你不需要声明说函数或者方法可能会抛出某种异常。受检异常在编译器被检查,java必须声明方法所会抛出的异常类型。
在Scala里,借用了模式匹配的思想来做异常的匹配,因此,在catch的代码里,是一系列case子句。



