一:包(package)
1:命名规则
只能包含数字、字母、下划线、小圆点,但不能用数字开头,也不能使用关键字
2:管理风格
// 用嵌套风格定义包
package com{
import com.atguigu.scala.Inner
// 在外层包中定义单例对象 //外层调用内层需要导包
object Outer{
var out:String = "out"
println(Inner.in)
}
package atguigu{
package scala{
// 内层包中定义单例对象
object Inner{
val in:String = "in"
def main(args: Array[String]): Unit = {
println(Outer.out) // 内层能直接使用外层变量
Outer.out = "outer"
println(Outer.out)
}
}
}
}
}
二:包对象
在Scala中可以为每个包定义一个同名的包对象,定义在包对象中的成员,作为其对应包下的class和object的共享变量,可以直接访问
不同的文件
//不同的文件
//文件1
package object chapter04 {
//定义当前包共享的属性和方法
val commonValue = "aaa"
def commmonValue(): Unit = {
println(s"$commonValue")
}
}
//文件2
package chapter04
object Test02 {
def main(args: Array[String]): Unit = {
commmonValue()
println(commonValue)
}
}
同一个文件
// 同一个文件,要保证包对象和包声明在同一作用域中
package com{
object Outer{
val out:String = "out"
def main(args:Array[String]):Unit = {
println(name)
}
}
}
package object com{
val name:String = "com"
}
三:类和对象
类:可以看出一个模板
对象:表示具体的事物
Java中一个.java有一个public类,Scala中没有public,一个.scala中可以写多个类
package chapter04
object Test03 {
def main(args: Array[String]): Unit = {
//创建一个对象
val student = new Student()
student.name //不能访问private属性
println(student.age)
println(student.sex)
student.sex = "female"
println(student.sex)
}
}
//定义一个类,不加修饰符,默认public
class Student{
//定义属性,不加修饰符,默认public
private var name:String = "alice"
var age:Int = _
var sex:String = _
}
四:封装
1:访问权限
1:Scala中的属性和方法默认都是public,但Scala中没有public
2:private为私有权限,只有在类的内部和伴生对象中可用
3:protect,同类、子类可以访问,同包无法访问
4:private增加包访问权限,包名下的其他类也可以使用
2:案例
package chapter04
object Test04 {
//创建对象
val person:Person = new Person()
println(person.age)
//name也不能访问
println(person.sex)
}
//定义一个子类
class Worker extends Person{
// idCard无法访问
override def printInfo(): Unit = {
println("worker...")
// println(idCard) 不能访问
name = "bob"
age = 25
sex = "male"
println(s"worker: $name $sex $age")
}
}
3:构造器格式
辅助构造器,函数的名称this,可以有多个,编译器通过参数的个数及类型来区分
辅助构造方法不能直接构建对象,必须直接或间接调用主构造方法
构造器调用其他另外的构造器,要求被调用构造器必须提前声明
class 类名(形参列表){ //主构造器
// 类体
def this(形参列表){ //辅助构造器
}
def this(形参列表){ //辅助构造器可以有多个...
}
}
4:案例
package chapter04
object Test05_Constructor {
def main(args: Array[String]): Unit = {
val student1 = new Student1
student1.Student1()
val student2 = new Student1("alice")
val student3 = new Student1("`bob",25)
}
}
//定义一个类
class Student1(){
//定义属性
var name:String = _
var age:Int = _
println("1.主构造方法被调用")
//声明辅助构造方法
def this(name:String){
this() //直接调用主构造器
println("2.辅助构造方法一被调用")
this.name = name
println(s"name:$name age:$age")
}
def this(name:String,age:Int){
this(name)
println("3.辅助构造方法二被调用")
this.age = age
println(s"name:$name age:$age")
}
def Student1():Unit = {
println("一般方法被调用")
}
}
5:构造器参数
主构造器参数1:未用任何修饰符修饰,这个参数就是一个局部变量
2:var修饰参数,作为类的成员属性使用,可以修改
3:val修饰参数,作为类只读属性使用,不能修改
package chapter04
object Test06_ConstructorParams {
def main(args: Array[String]): Unit = {
val student2 = new Student2
println(s"student2:name = ${student2.name},age = ${student2.age}")
val student3 = new Student3("bob",20)
println(s"student2:name = ${student3.name},age = ${student3.age}")
val student4 = new Student4("cary",20)
// println(s"student2:name = ${student4.name},age = ${student4.age}") //获取不到,主构造器参数列表没有修饰符,不是属性值
student4.printInfo()
val student5 = new Student5("bob",20)
println(s"student2:name = ${student5.name},age = ${student5.age}")
// student5.age = 21 // val 不可变 error
}
}
//定义类
//无参构造器
class Student2{
//单独定义属性
var name:String = _
var age:Int = _
}
//上面定义等价于
class Student3(var name:String,var age:Int)
//主构造器参数无修饰
class Student4(name:String,age:Int){
def printInfo(): Unit ={
println(s"student4 name = ${name} , age = ${age}")
}
}
class Student5(val name:String,val age:Int)
class Student6(var name:String,var age:Int){
var school:String = _
def this(name:String,age:Int,school:String){
this(name,age)
this.school = school
}
}
五:继承
1:基本语法
class 子类名 extends 父类名{类体}
子类继承父类的属性和方法
Scala是单继承
2:案例
package chapter04
object Test07_Inherit {
def main(args: Array[String]): Unit = {
val student1 = new Student7("alice",18)
val student2 = new Student7("bob",20,"std001")
}
}
//定义一个父类
class Person7(){
var name:String = _
var age:Int = _
println("1.父类的主构造器调用")
def this(name:String,age:Int){
this()
println("2.父类的辅助构造器被调用")
this.name = name
this.age = age
}
def printInfo():Unit = {
println(s"Person:$name $age")
}
}
//定义子类
class Student7(name:String,age:Int) extends Person7{
var stdNo:String = _
println("3.子类的主构造器调用")
def this(name:String,age:Int,stdNo:String){
this(name,age)
println("4.子类的辅助构造器调用")
this.stdNo = stdNo
}
}
六:多态(子类的对象赋给父类的引用)
1:Scala,方法和属性都动态绑定
class Person {
val name: String = "person"
def hello(): Unit = {
println("hello person")
}
}
class Teacher extends Person {
override val name: String = "teacher"
override def hello(): Unit = {
println("hello teacher")
}
}
object Test {
def main(args: Arra y[String]): Unit = {
val teacher: Teacher = new Teacher()
println(teacher.name)
teacher.hello()
val teacher1: Person = new Teacher
println(teacher1.name)
teacher1.hello()
}
}
//结果
teacher
hello teacher
teacher
hello teacher
2:Java,方法动态绑定,但是属性并没有动态绑定
class Person {
public String name = "person";
public void hello() {
System.out.println("hello person");
}
}
class Teacher extends Person {
public String name = "teacher";
@Override
public void hello() {
System.out.println("hello tea cher");
}
}
public class TestDynamic {
public static void main(String[] args) {
Teacher teacher = new Teacher();
Person teacher1 = new Teacher();
System.out.println(teacher.name);
teacher.hello();
System.out.println(teacher1.name);
teacher1.hello();
}
}
//结果
teacher
hello teacher
person
hello teacher
七:抽象类
1:抽象属性和抽象方法
定义抽象类:abstract class Person(){} //通过abstract关键字标记抽象类
定义抽象属性:val | var name:String //一个属性没有初始化,就是抽象属性
定义抽象方法:def hello():String //只声明而没有实现的方法,就是抽象方法
2:案例
package chapter05
object AbstractClass {
def main(args: Array[String]): Unit = {
}
}
//定义抽象类
abstract class Person9{
//非抽象属性
val name:String = "person"
//抽象属性
var age:Int
//非抽象方法
def eat():Unit={
println("person eat")
}
//抽象方法
def sleep():Unit
}
//定义具体的实现子类
class Student9 extends Person9{
var age:Int = 18
def sleep(): Unit = {
println("student sleep")
}
//重写非抽象属性和方法
override val name: String = "student"
override def eat(): Unit = {
println("student eat")
}
}
3:继承&重写
1:如果父类为抽象类,那么子类需要将抽象的属性和方法实现,否则子类也需声明为抽象类
2:重写非抽象方法需要用override修饰,重写抽象方法则可以不加override
3:子类中调用父类的方法使用super关键字
4:子类对抽象属性进行实现,父类抽象属性可以用var修饰
子类对非抽象属性重写,父类非抽象属性只支持val类型,而不支持var
4:匿名子类
package chapter05
object AnnoymousClass {
def main(args: Array[String]): Unit = {
val person:Person10 = new Person10 {
override var name: String = "alice"
override def eat(): Unit = println("person eat")
}
println(person.name)
person.eat()
}
}
//定义抽象类
abstract class Person10{
var name:String
def eat():Unit
}
八:单例对象,伴生对象
1:背景
Java代码中的静态属性和方法,都是通过类名来调用的,没有做到面向对象
Scala将static关键字去掉,需要全局的属性和方法,引入了单例对象
2:基本语法
object Person{
val country:String="China"
}
3:说明
1:单例对象采用object关键字声明
2:单例对象对应的类称之为伴生类,伴生对象的名称应该和伴生类名一致
3:单例对象中的属性和方法都可以通过伴生对象名,类名直接调用访问
4:案例
package chapter05
object Test11_Object {
def main(args: Array[String]): Unit = {
val student = new Student11("alice",18)
student.printInfo()
}
}
//定义类
class Student11(val name:String,val age:Int){
def printInfo(): Unit ={
println(s"student:name=${name},age=$age,school=${Student11.school}")
}
}
//伴生对象
object Student11{
val school:String = "atguigu"
}
九:特质
1:背景
特质,trait,代替接口,多个类具有相同的特质时,就可以将这个特质独立出来,使用trait
trai既可以有抽象属性和方法, 也可以有具体的属性和方法,一个类可以混入多个特质
2:声明
trait 特质名{
trait 主体
}
3:案例
package chapter05
object Test13_Trait {
def main(args: Array[String]): Unit = {
val student = new Studednt13
student.sayHello()
student.study()
student.datting()
student.play()
}
}
//定义一个父类
class Person13{
val name:String = "person"
val age:Int = 18
def sayHello():Unit={
println("hello from:"+name)
}
}
//定义一个特质
trait Young{
//声明抽象和非抽象属性
var age:Int
val name:String = "young"
//声明抽象和非抽象方法
def play():Unit={
println("young people is playing")
}
def datting():Unit
}
class Studednt13 extends Person13 with Young{
//重写冲突的属性
override val name: String = "student"
//实现抽象方法
def datting(): Unit = println(s"student $name is datting")
//
def study():Unit = println(s"student $name is studying")
// 重写父类方法
override def sayHello(): Unit = {
super.sayHello()
println(s"hello from:student $name")
}
}
4:基本语法
一个类具有某种特质,就意味着这个类满足了这个特质的所有要素,所以在使用时,也采用了extends关键字,如果有多个特质或存在父类,那么需要采用with关键字
没有父类:class 类名 extends 特质1 with 特质2 with 特质3...
有父类:class 类名 extends 父类 with 特质1 with 特质2 with 特质3...
5:特质混入案例
package chapter05
object Test14_TraitMixin {
def main(args: Array[String]): Unit = {
val student = new Studednt14
student.study()
student.increase()
student.play()
student.increase()
student.datting()
student.increase()
println("==============")
//动态混入
val studentWithTalent = new Studednt14 with Talent{
override def dancing(): Unit = println("student is good at dancing")
override def singing(): Unit = println("student is good at singing")
}
studentWithTalent.sayHello()
studentWithTalent.play()
studentWithTalent.study()
}
}
//再定义一个特质
trait Knowledge{
var amount:Int = 0
def increase():Unit
}
trait Talent{
def singing():Unit
def dancing():Unit
}
class Studednt14 extends Person13 with Young with Knowledge {
//重写冲突的属性
override val name: String = "student"
//实现抽象方法
def datting(): Unit = println(s"student $name is datting")
//
def study():Unit = println(s"student $name is studying")
// 重写父类方法
override def sayHello(): Unit = {
super.sayHello()
println(s"hello from:student $name")
}
override def increase(): Unit = {
amount += 1
println(s"student $name knowledge increased: $amount")
}
}
6:特质叠加
就是一个类,继承有父类和其他特质。
然后假如说父类和特质有重复的属性的时候,需要重写一下即可。
假如说时父类和特质有重复的方法的时候,也需要重新,但这个重新会调用super的方法,这个super指的是,最后一个with关键字的内容,即最后面的内容
package chapter05
object Test15_TraitOverlying {
def main(args: Array[String]): Unit = {
val student = new Student15
student.increase()
}
}
//
//再定义一个特质
trait Knowledge15{
var amount:Int = 0
def increase():Unit = {
println("knowledge increased")
}
}
trait Talent15{
def singing():Unit
def dancing():Unit
def increase():Unit = {
println("talent increased")
}
}
class Student15 extends Person13 with Talent15 with Knowledge15{
override def dancing(): Unit = println("dancing")
override def singing(): Unit = println("singing")
override def increase(): Unit = {
super.increase()
}
}
7:钻石叠加继承问题
package chapter05
object Test15_TraitOverlying {
def main(args: Array[String]): Unit = {
val student = new Student15
student.increase()
//钻石问题特质叠加
val myFootBall = new MyFootBall
println(myFootBall.describe())
}
}
//定义球类特征
trait Ball{
def describe():String = "ball"
}
//定义颜色特质
trait ColorBall extends Ball{
var color:String = "red"
override def describe(): String = color + "-" + super.describe()
}
//定义种类特征
trait CategoryBall extends Ball{
var category:String = "foot"
override def describe(): String = category + "-" + super.describe()
}
//定义一个自定义球类
class MyFootBall extends CategoryBall with ColorBall{
override def describe(): String = "my ball is " + super.describe()
}
//再定义一个特质
trait Knowledge15{
var amount:Int = 0
def increase():Unit = {
println("knowledge increased")
}
}
trait Talent15{
def singing():Unit
def dancing():Unit
def increase():Unit = {
println("talent increased")
}
}
class Student15 extends Person13 with Talent15 with Knowledge15{
override def dancing(): Unit = println("dancing")
override def singing(): Unit = println("singing")
override def increase(): Unit = {
super.increase()
}
}
8:抽象类和特质的区别
1:优先使用特质。一个类扩展多个特质很方便,但只能扩展一个抽象类
2:如果需要构造函数参数,使用抽象类,因为抽象类可以定义带参数的构造函数,特质不行