Scala OOP

前序

1、Scala 为纯粹OOP
	1.1、不支持基本类型:一切皆为对象 Byte,Int,... 
	1.2、不支持静态关键字:static
	1.3、支持类型推断,和类型预定,动静结合

/*
	关键字:class
	创建对象:new
	内含:成员变量和方法
	区别:
		1、默认访问修饰符为 public,也支持 private 和 protected
		2、没有构造方法,通过构造参数列表实现对象创建
*/
// 主构造器
class Point(x:Int,y:Int) {
  var _x:Int = x
  var _y:Int = y

  def move(offsetX:Int,offsetY:Int): Unit = {
    _x += offsetX
    _y += offsetY
  }

  override def toString: String = s"Point{x=${_x},y=${_y}}"
}

val p = new Point(0,0)
p.move(15,32)
p.x
p.y
修饰符类(class)伴生对象(object)子类(subclass)同包(package)全局(world)
default(public)YYYYY
protectedYYYNN
privateYYNNN
// 辅助构造器:基于主构造器的重载
class Student(name:String,age:Int) {
  private var _name:String = name
  private var _age:Int = age
  
  // 辅助构造器
  def this() = this("Unknown",0)
  def this(name:String) = this(name,18)

  def getName:String = _name
  def getAge:Int = _age

  def setName(name:String):Unit = _name = name
  def setAge(age:Int):Unit = _age = age

  override def toString(): String = s"Student{name=${_name},age=${_age}}"
}

val stu1 = new Student("张三", 20)
val stu2 = new Student()
val stu3 = new Student("henry")

继承

/*
	extends & override
*/
class ColorPoint(x:Int,y:Int,color:Boolean) extends Point(x:Int,y:Int) {
  var _color:Boolean = color

  private def getColor = if(_color) "red" else "black"

  override def move(offsetX: Int, offsetY: Int): Unit = {
    _x += offsetX*2
    _y += offsetY*2
    println(s"$getColor point moved to {${_x},${_y}}")
  }

  override def toString: String = s"$getColor point ${super.toString}"
}

val cp = new ColorPoint(0,0,true)
println(cp)
cp.move(12,25)
/*
	red point now at {0,0}
	red point moved to {24,50}
*/

抽象类

/*
	abstract & extends & override
	抽象类中可以有抽象方法(没有方法体的方法即抽象方法)
	无法实例化
	使用 abstract 关键字修饰
	子类重写父类【抽象】方法可以省略 override 关键字,但不推荐省略
	子类重写父类【非抽象】方法必须写 override 关键字
*/
abstract class Shape {
  def draw():Unit // 抽象方法
}

class Circle extends Shape{
  override def draw(): Unit = {
    println("drawing a circle")
  }
}

val shape = new Circle
shape.draw()

单例对象

/*
	代替 Java 中的 static 关键字
	1、关键字:object
	2、可以包含属性和方法,且可以通过单例对象名直接调用
	3、采取惰性模式,第一次被访问时创建
	4、无构造器,且不能 new
	5、程序入口方法必须定义在单例对象中
	6、同一个文件中同名的类和单例对象形成绑定关系,并称之为伴生类和伴生对象
*/
// 文件名:Student.scala
// 伴生类
class Student(name:String,age:Int) {
  private var _name:String = name
  private var _age:Int = age

  def this() = this("Unknown",0)
  def this(name:String) = this(name,18)

  def getName:String = _name
  def getAge:Int = _age

  def setName(name:String):Unit = _name = name
  def setAge(age:Int):Unit = _age = age

  override def toString(): String = s"Student{name=${_name},age=${_age}}"
}
// 伴生对象
object Student{
  var products:Array[String] = Array("BigData","Cloud")

  def apply(name: String, age: Int): Student = new Student(name, age)

  def add(a:Int,b:Int) = a+b
}

Student.products.foreach(println)
val rst: Int = Student.add(2, 3)
val stu1 = new Student("张三", 20)
// 自动调用 apply 完成 Student 对象构造 
val stu2 = Student("ariel",22)

/*
【 练习一 】
    需求说明
    假设类Book有属性title和author(多个),books是Book的列表
    实现Book类,同时使用主构造器与辅助构造器
    实现Book的伴生对象,使用伴生对象创建Book实例
    创建books,使用List[Book]初始化5个以上Book实例
    找出books中书名包含“xxx”的书,并打印书名
    找出books中作者名以“xxx”打头的书,并打印书名
*/
val list = List(
    Book("武侠:最强小保安",Array("张三","李四","王五")),
    Book("都市:上门赘婿",Array("阿强","洞冥福","花花")),
    Book("武侠:翔龙会",Array("阿庆嫂","黄世仁")),
    Book("都市:缘起",Array("徐世明","张丘月")),
    Book("武侠:小李飞刀",Array("王栋","李宏","张明")),
)

特质

/*
	is a : extends
	has a : implements|with
	
	关键字:trait & extends & with & override
	1、包含字段、方法,亦可包含字段和方法的实现
	2、类、单例对象、普通对象都可以扩展特质
	3、没有构造器,不能实例化
	4、单根继承,借助 with 实现多混入
*/
abstract class Animal {
  val info:String = "动物描述类"
  val name:String

  def showMe:Unit = println(s"This is dog $name")
  def cry():Unit
}

trait ByFoot {
  def jog():Unit
  def run():Unit
}

class Dog(dogName:String) extends Animal {
  override val name: String = dogName
  override def cry(): Unit = println(s"Dog $name is crying...")
}
object Dog{
  def apply(dogName: String): Dog = new Dog(dogName)
}

object Cat extends Animal with ByFoot {
  override val name: String = "加云"
  override def cry(): Unit = println(s"Cat $name is crying...")
  override def jog(): Unit = println(s"Cat $name is jogging...")
  override def run(): Unit = println(s"Cat $name is running...")
}

val xq = Dog("小强")
xq.cry()

val jy = Cat
jy.cry()
jy.jog()
jy.run()

动态混入

// 动态强制混入特质:只能定义一个强制混入特质,且必须位于类内首行
// self 是 this 的别名
class Penguin {
  self:Animal=>						// 强制混入特质语法
  val brand:String = "企鹅"
}
// 复合类型 Penguin with Animal
val penguin: Penguin with Animal = new Penguin() with Animal {
    override val name: String = "阿童木"
    override def cry(): Unit = println(s"$brand $name is crying")
}
penguin.cry()

// 动态非强制混入特质 with,支持多混入
class Bear(nickName:String) {
  val _name:String = nickName
}
val bear: Bear = new Bear("熊大") with Animal with ByFoot {
    override val name: String = "狗熊"
    override def cry(): Unit = println(s"$name ${_name} is crying")
    override def jog(): Unit = println(s"$name ${_name} is jogging")
	override def run(): Unit = println(s"$name ${_name} is running")
}
bear.cry()
bear.jog()
bear.run()

抽象类 VS 特质

/*
	一般【优先使用特质】:
		1、抽象类在于多类公共属性和行为的抽象,重点在于封装思想,本质为类,单继承,不支持多混入
		2、接口在于一类事物的属性和行为标准定义,重点在于多态思想,支持多混入,动态混入
	若需要带参构造,只能使用抽象类
*/

/*
【 练习二 】
    需求说明
        现在Book拥有电子版本,可以在多终端上播放
        	属性:作者author:String,书名bookName:String,类型bookType:String
        		 内容chapters:Array[String]
        	方法:简介resume():Unit
        定义Ebook特质
        	方法:play()
        使Book动态混入Ebook特质,实现play()方法
*/
val chapters = Array(
      "“春游浩荡,是年年寒食,梨花时节。白锦无纹香烂漫,玉树琼苞堆雪。静夜沉沉,浮光霭霭,冷浸溶溶月。人间天上,烂银霞照通彻。浑似姑射真人,天姿灵秀,意气殊高洁。万蕊参差谁信道,不与群芳同列。浩气清英,仙才卓荦,下土难分别。瑶台归去,洞天方看清绝。”\n\n  作这一首《无俗念》词的,乃南宋末年一位武学名家,有道之士。此人姓丘,名处机,道号长春子,名列全真七子之一,是全真教中出类拔萃的人物。《词品》评论此词道:“长春,世之所谓仙人也,而词之清拔如此”。这首词诵的似是梨花,其实词中真意却是赞誉一位身穿白衣的美貌少女,说她“浑似姑射真人,天姿灵秀,意气殊高洁”,又说她“浩气清英,仙才卓荦”,“不与群芳同列”。词中所颂这美女,乃古墓派传人小龙女。她一生爱穿白衣,当真如风拂玉树,雪裹琼苞,兼之生性清冷,实当得起“冷浸溶溶月”的形容,以“无俗念”三字赠之,可说十分贴切。长春子丘处机和她在终南山上比邻而居,当年一见,便写下这首词来。\n\n  这时丘处机逝世已久,小龙女也已嫁与神雕大侠杨过为妻。在河南少室山山道之上,却另有一个少女,正在低低念诵此词。这少女十**岁年纪,身穿淡黄衣衫,骑着一头青驴,正沿山道缓缓而上,心中默想:“也只有龙姊姊这样的人物,才配得上他。”这一个“他”字,指的自然是神雕大侠杨过了。她也不拉缰绳,任由那青驴信步而行,一路上山。过了良久,她又低声吟道:“欢乐趣,离别苦,就中更有痴儿女。君应有语,渺万里层云,千山暮雪,只影向谁去?”",
      "她腰悬短剑,脸上颇有风尘之色,显是远游已久;韶华如花,正当喜乐无忧之年,可是容色间却隐隐有懊闷意,似是愁思袭人,眉间心上,无计回避。\n\n  这少女姓郭,单名一个襄字,乃大侠郭靖和女侠黄蓉的次女,有个外号叫做“小东邪”。她一驴一剑,只身漫游,原想排遣心中愁闷,岂知酒入愁肠固然愁上加愁,而名山独游,一般的也是愁闷徒增。河南少室山山势颇陡,山道却是一长列宽大的石级,规模宏伟,工程着实不小,那是唐朝高宗为临幸少林寺而开凿,共长八里。郭襄骑着青驴委折而上,只见对面山上五道瀑布飞珠溅玉,奔泻而下,再俯视群山,已如蚁蛭。顺着山道转过一个弯,遥见黄墙碧瓦,好大一座寺院。\n\n  她望着连绵屋宇出了一会神,心想:“少林寺向为天下武学之源,但华山两次论剑,怎地五绝之中并无少林寺高僧?难道寺中和尚自忖没有把握,生怕堕了威名,索性便不去与会?又难道众僧侣修为精湛,名心尽去,武功虽高,却不去和旁人争强赌胜?”她下了青驴,缓步走向寺前,只见树木森森,荫着一片碑林。石碑大半已经毁破,字迹模糊,不知写着些甚么。心想:“便是刻凿在石碑上的字,年深月久之后也须磨灭,如何刻在我心上的,却是时日越久反而越加清晰?”瞥眼只见一块大碑上刻着唐太宗赐少林寺寺僧的御札,嘉许少林寺僧立功平乱。碑文中说唐太宗为秦王时,带兵讨伐王世充,少林寺和尚投军立功,最著者共一十三人。其中只昙宗一僧受封为大将军,其余十二僧不愿为官,唐太宗各赐紫罗袈裟一袭。她神驰想象:“当隋唐之际,少林寺武功便已名驰天下,数百年来精益求精,这寺中卧虎藏龙,不知有多少好手。”郭襄自和杨过、小龙女夫妇在华山绝顶分手后,三年来没得到他二人半点音讯。她心中长自记挂,于是禀明父母,说要出来游山玩水,实则是打听杨过的消息,她倒也不一定要和他夫妇会面,只须听到一些杨过如何在江湖上行侠的讯息,也便心满意足了。偏生一别之后,他夫妇从此便不在江湖上露面,不知到了何处隐居,郭襄自北而南,又从东至西,几乎踏遍了大半个中原,始终没听到有人说起神雕大侠杨过的近讯。这一日她到了河南,想起少林寺中有一位僧人无色禅师是杨过的好友,自己十六岁生日之时,无色瞧在杨过的面上,曾托人送来一件礼物,虽然从未和他见过面,但不妨去问他一问,说不定他会知道杨过的踪迹,这才上少林寺来。正出神间,忽听得碑林旁树丛后传出一阵铁链当啷之声,一人诵念佛经:“是时药叉共王立要,即于无量百千万亿大众之中,说胜妙伽他曰:由爱故生忧,由爱故生怖;若离于爱者,无忧亦无怖……”郭襄听了这四句偈言,不由得痴了,心中默默念道:“由爱故生忧,由爱故生怖;若离于爱者,无忧亦无怖。”只听得铁链拖地和念佛之声渐渐远去。郭襄低声道:“我要问他,如何才能离于爱,如何能无忧无怖?”随手将驴缰在树上一绕,拨开树丛,追了过去。只见树后是一条上山的小径,一个僧人挑了一对大桶,正缓缓往山上走去。郭襄快步跟上,奔到距那僧人七八丈处,不由得吃了一惊,只见那僧人挑的是一对大铁桶,比之寻常水桶大了两倍有余,那僧人颈中、手上、脚上,更绕满了粗大的铁链,行走时铁链拖地,不停发出声响。这对大铁桶本身只怕便有二百来斤,桶中装满了水,重量更是惊人。郭襄叫道:“大和尚,请留步,小女子有句话请教。”",
      "那僧人回过头来,两人相对,都是一愕。原来这僧人便是觉远,三年以前,两人在华山绝顶曾有一面之缘。郭襄知他虽然生性迂腐,但内功深湛,不在当世任何高手之下,便道:“我道是谁,原来是觉远大师。你如何变成了这等模样?”觉远点了点头,微微一笑,合十行礼,并不答话,转身便走。郭襄叫道:“觉远大师,你不认得我了么?我是郭襄啊。”觉远又是回首一笑,点了点头,这次更不停步。郭襄又道:“是谁用铁链绑住了你?如何这般虐待你?”觉远左掌伸到脑后摇了几摇,示意她不必再问。\n\n  郭襄见了这等怪事,如何肯不弄个明白?当下飞步追赶,想抢在他面前拦住,岂知觉远虽然全身带了铁链,又挑着一对大铁桶,但郭襄快步追赶,始终抢不到他身前。郭襄童心大起,展开家传轻功,双足一点,身子飞起,伸手往铁桶边上抓去,眼见这一下必能抓中。不料落手时终究还是差了两寸。郭襄叫道:“大和尚,这般好本事,我非追上你不可。”但见觉远不疾不徐的迈步而行,铁链声当啷当啷有如乐音,越走越高,直至后山。郭襄直奔得气喘渐急,但仍和他相距丈余,不由得心中佩服:“爹爹妈妈在华山之上,便说这位大和尚武功极高,当时我还不大相信,今日一试,才知爹妈的话果然不错。”只见觉远转身走到一间小屋之后,将铁桶中的两桶水都倒进了一口井中。郭襄大奇,叫道:“大和尚,你莫非疯了,挑水倒在井中干么?”觉远神色平和,只摇了摇头。郭襄忽有所悟,笑道:“啊,你是在练一门高深的武功。”觉远又摇了摇头。郭襄心中着恼,说道:“我刚才明明听得你在念经,又不是哑了,怎地不答我的话?”觉远合十行礼,脸上似有歉意,一言不发,挑了铁桶便下山去。郭襄探头井口向下望去,只见井水清澈,也无特异之处,怔怔望着觉远的背影,心中满是疑窦。她适才一阵追赶,微感心浮气躁,于是坐在井栏圈上,观看四下风景,这时置身处已高于少林寺所有屋宇,但见少室山层崖刺天,横若列屏,崖下风烟飘渺,寺中钟声随风送上,令人一洗烦俗之气。郭襄心想:“这和尚的弟子不知在哪里,和尚既不肯说,我去问那个少年便了。”当下信步落山,想去找觉远的弟子张君宝来问。走了一程,忽听得铁链声响,觉远又挑了水上来。郭襄闪身躲在树后,心想:“我暗中瞧瞧他到底在捣甚么鬼。”铁链声渐近,只见觉远仍是挑着那对铁桶,手中却拿着一本书,全神贯注的轻声诵读。郭襄待他走到身边,猛地里跃出,叫道:“大和尚,你看甚么书?”\n\n  觉远失声叫道:“啊哟,吓了我一跳,原来是你。”郭襄笑道:“你装哑巴装不成了罢,怎么说话了?”觉远微有惊色,向左右一望,摇了摇手。郭襄道:“你怕甚么?”觉远还未回答,突然树林中转出两个灰衣僧人,一高一矮。那瘦长僧人喝道:“觉远,不守戒法,擅自开口说话,何况又和庙外生人对答,更何况又和年轻女子说话?这便见戒律堂首座去。”觉远垂头丧气,点了点头,跟在那两个僧人之后。郭襄大为惊怒,喝道:“天下还有不许人说话的规矩么?我识得这位大师,我自跟他说话,干你们何事?”那瘦长僧人白眼一翻,说道:“千年以来,少林寺向不许女流擅入。姑娘请下山去罢,免得自讨没趣。”郭襄心中更怒,说道:“女流便怎样?难道女子便不是人?你们干么难为这位觉远大师?既用铁链捆绑他,又不许他说话?”那僧人冷冷的道:“本寺之事,便是皇帝也管不着。何劳姑娘多问?”",
      "郭襄怒道:“这位大师是忠厚老实的好人,你们欺他仁善,便这般折磨于他,哼哼,天鸣禅师呢?无色和尚、无相和尚在哪里?你去叫他们出来,我倒要问问这个道理。”两个僧人听了都是一惊。天鸣禅师是少林寺方丈,无色禅师是本寺罗汉堂首座,无相禅师是达摩堂首座,三人位望尊崇,寺中僧侣向来只称“老方丈”、“罗汉堂座师”、“达摩堂座师”,从来不敢提及法名,岂知一个年轻女子竟敢上山来大呼小叫,直斥其名。那两名僧人都是戒律堂首座的弟子,奉了座师之命,监视觉远,这时听郭襄言语莽撞,那瘦长僧人喝道:“女施主再在佛门清净之地滋扰,莫怪小僧无礼。”\n\n  郭襄道:“难道我还怕了你这和尚?你快快把觉远大师身上的铁链除去,那便算了,否则我找天鸣老和尚算帐去。”那矮僧听郭襄出言无状,又见她腰悬短剑,沉着嗓子道:“你把兵刃留下,我们也不来跟你一般见识,快下山去罢。”郭襄摘下短剑,双手托起,冷笑道:“好罢,谨遵台命。”那矮僧自幼在少林寺出家,一向听师伯、师叔、师兄们说少林寺是天下武学的总源,又听说不论名望多大、本领多强的武林高手,从不敢携带兵刃走进少林寺出门。这年轻姑娘虽然未入寺门,但已在少林寺范围之内,只道她真是怕了,乖乖交出短剑,于是伸手便去接剑。他手指刚碰到剑鞘,突然间手臂剧震,如中电掣,但觉一股强力从短剑上传了过来,推得他向后急仰,立足不定,登时摔倒。他身在斜坡之上,一经摔倒,便骨碌碌的向下滚了数丈,好容易硬生生的撑住,这才不再滚动。那瘦长僧人又惊又怒,喝道:“你吃了狮子心豹子胆,竟到少林寺撒野来啦!”转过身来,踏上一步,右手一拳击出,左掌跟着在右拳上一搭,变成双掌下劈,正是“闯少林”第二十八势“翻身劈击”。郭襄握住剑柄,连剑带鞘向他肩头砸去。那僧人沉肩回掌,来抓剑鞘。觉远在旁瞧得惶急,大叫:“别动手,别动手!有话好说。”便在此时,那僧人右手已抓住剑鞘,正却运劲里夺,猛觉手心一震,双臂隐隐酸麻,只叫得一声:“不好!”郭襄左腿横扫,已将他踢下坡去。他所受的这一招比那矮僧重得多,一路翻滚,头脸上擦出不少鲜血,这才停住。郭襄心道:“我上少林寺来是打听大哥哥的讯息,平白无端的跟他们动手,当真好没来由。”眼见觉远愁眉苦脸的站在一旁,当即抽出短剑,便往他手脚上的铁链削去。这短剑虽非稀世奇珍,却也是极锋锐的利器,只听得当啷啷几声响,铁链断了三条。觉远连呼:“使不得,使不得!”郭襄道:“甚么使不得?”指着正向寺内奔去的高矮二僧说道:“这两个恶和尚定是奔去报讯,咱们快走。你那个姓张的小徒儿呢?带了他一起走罢!”觉远只是摇手。忽听得身后一人说道:“多谢姑娘关怀,小的在这儿。”\n\n  郭襄回过头来,只见身后站着个十六七岁的少年,粗眉大眼,身材魁伟,脸上却犹带稚气,正是三年前曾在华山之巅会过的张君宝。比之当日,他身形已高了许多,但容貌无甚改变。郭襄大喜,说道:“这里的恶和尚欺侮你师父,咱们走罢。”张君宝摇头道:“没有谁欺侮我师父啊。”郭襄指着觉远道:“那两个恶和尚用铁链锁着你师父,连一句话也不许他说,还不是欺侮?”觉远苦笑摇头,指了指山下,示意郭襄及早脱身,免惹事端。郭襄明知少林寺中武功胜过她的人不计其数,但既见了眼前的不平之事,决不能便此撒手不顾;可是却又担心寺中好手出来截拦,当下一手拉了觉远,一手拉了张君宝,顿足道:“快走快走,有甚么事,下山去慢慢说不好么?”两人只是不动。忽见山坡下寺院边门中冲出七八名僧人,手提齐眉木棍,吆喝道:“哪里来的野姑娘,胆敢来少林寺撒野?”张君宝提起嗓子叫道:“各位师兄不得无礼,这位是……”郭襄忙道:“别说我名字。”她想今日的祸事看来闯得不小,说不定闹下去会不可收拾,可别牵累到爹爹妈妈,又补上一句:“咱们翻山走罢!千万别提我爹爹妈妈和朋友的姓名。”只听得背后山顶上吆喝声响,又涌出七八名僧人来。郭襄见前后都出现了僧人,秀眉深蹙,急道:“你们两个婆婆妈妈,没点男子汉气概!到底走不走?”张君宝道:“师父,郭姑娘一片好意……”",
      "便在此时,下面边门中又窜出四名黄衣僧人,飕飕飕的奔上坡来,手中都没兵器,但身法迅捷,衣襟带风,武功颇为了得。郭襄见这般情势,便想单独脱身亦已不能,索性凝气卓立,静观其变。当先一名僧人奔到离她四丈之处,朗声说道:“罗汉堂首座尊师传谕:着来人放下兵刃,在山下一苇亭中陈明详情,听由法谕。”\n\n  郭襄冷笑道:“少林寺的大和尚官派十足,官腔打得倒好听。请问各位大和尚做的是大宋皇帝的官儿呢,还是做蒙古皇帝的官?”这时淮水以北,大宋国土均已沦陷,少林寺所在之地自也早该归蒙古管,只是蒙古大军连年进攻襄阳不克,忙于调兵遣将,也无余力来理会丛林寺观的事,因此少林寺一如其旧,与前并无不同。那僧人听郭襄讥刺之言甚是厉害,不由得脸上一红,心中也觉对外人下令传谕有些不妥,合十说道:“不知女施主何事光临敝寺,且请放下兵刃,赴山下一苇亭中奉茶说话。”郭襄听他语转和缓,便想乘此收蓬,说道:“你们不让我进寺,我便希罕了?哼,难道少林寺中有宝,我见一见便沾了光么?”向张君宝使个眼色,低声道:“到底走不走?”张君宝摇摇头,嘴角向觉远一努,意思说是要服侍师父。郭襄朗声道:“好,那我不管啦,我走了。”拔步便下坡去。第一名黄衣僧侧身让开。第二名和第三名黄衣僧却同时伸手一拦,齐声道:“且慢,放下了兵刃。”郭襄眉毛一扬,手按剑柄。第一名僧人道:“我们也不敢留着女施主的兵刃。女施主一到山下,我们立即将宝剑送上,这是少林寺千年来的规矩,还请包涵。”郭襄听他言语有礼,心下踌躇:“倘若不留短剑,势必有场争斗,我孤身一人,如何是阖寺僧众的敌手?但若留下短剑,岂不将外公、爹爹、妈妈、大哥哥、龙姊姊的面子一古脑儿都丢得干净?”她一时沉吟未决,蓦地里眼前黄影晃动,一人喝道:“到少林寺来既带剑,又伤人,世上焉有是理?”跟着劲风飒然,五只手指往剑鞘上抓下来。这僧人若不贸然出手,郭襄一番迟疑之后,多半便会将短剑留下。她和乃姊郭芙的性子大不相同,虽然豪爽,却不鲁莽,眼前处境既极度不利,便会暂忍一时之气,日后再去和外公、爹妈商量,回头找这场子,但对方突然逞强,岂能眼睁睁的让他将剑夺去?那僧人的擒拿手法既狠且巧,一抓住剑鞘,心想郭襄定会向里回夺,一个和尚跟一个年轻女子拉拉扯扯,大是不雅,当下运劲向左斜推,跟着抓而向右。郭襄被他这么一推一抓,果然已拿不牢剑鞘,当即握住剑柄,刷的一声,寒光出匣。那僧人右手将剑鞘夺了过去,左手却有两根手指被短剑顺势割断,剧痛之下,抛下剑鞘,往旁退开。\n\n  众僧人见同门受伤,无不惊怒,挥杖舞棍,一齐攻来。郭襄心想:“一不做二不休,反正今日已不能善罢。”当下使出家传的“落英剑法”,便往山下冲去。众僧人排成三列,仰面挡住。那“落英剑法”乃黄药师从“落英掌法”的路子中演化来,虽不若“玉箫剑法”的精妙,却也是桃花岛的一绝,但见青光激荡,剑花点点,便似落英缤纷,四散而下,霎时间僧人中又有两人受伤。但背后数名僧人跟着抢到,居高临下的夹攻。按理郭襄早已抵挡不住,只是少林僧众慈悲为本,不愿伤她性命,所出招数都非杀手,只求将她打倒,训诫一番,扣下兵刃,将她逐下山去。可是郭襄剑光错落,却也不易攻近身去。众僧初时只道一个妙龄女郎,还不轻易打发?待见她剑法精奇,始知她若非名门之女,便是名师之徒,多半得罪不得,出招时更有分寸,一面急报罗汉堂首座无色禅师。正斗之间,一个身材高瘦老年僧人缓步走近,双手笼在袖中,微笑观斗。两名僧人走到他身前,低声禀告了几句。郭襄已斗得气喘吁吁,剑法凌乱,大声喝道:“说甚么天下武学之源,原来是十多个和尚一拥而上,倚多为胜。”那老僧便是罗汉堂首座无色禅师,听她这么说,便道:“各人住手!”众僧人立时罢手跃开。无色禅师道:“姑娘贵姓,令尊和令师是谁?光临少林寺,不知有何贵干?”郭襄心道:“我爹娘的姓名不能告诉你。我到少林寺来是为了打听大哥哥的讯息,那也不能当众述说。眼下已闹成这等模样,日后爹娘和大哥哥知道了定要怪我,不如悄悄的溜了罢。”说道:“我的姓名不能跟你说,我不过见山上风景优美,这便上来游览玩耍。原来少林寺比皇宫内院还要厉害,动不动便要扣人家兵刃。请问大师,我进了贵寺的山门没有?当日达摩祖师传下武艺,想来也不过教众僧侣强身健体,便于精进修为,想不到少林寺名头越大,武功越高,恃众逞强的名头也越来越响。好,你们要扣我兵刃,这便留下,除非将我杀了,否则今日之事江湖上不会无人知晓。”她本来伶牙俐齿,这件事也并非全是她的过错,一席话只将无色禅师说得哑口无言。郭襄鉴貌辨色,心想:“这番胡闹我固怕人知晓,看来少林寺更加不愿张扬。十多个和尚围斗一个年轻姑娘,说出去有甚么好听?”当下哼的一声,将短剑往地下一掷,举步便行。"
)
val book = Book("张三","倚天屠龙记","武侠小说")

内部类

/*
	Java中内部类是【外部类的成员】:
		InClass ic = new OutClass.InClass()
	Scala中内部类是【外部类对象的成员】:
		val oc = new OutClass();
		val ic = new oc.InClass();
*/
class OutClass(name:String,age:Int,gender:String,school:String,major:String) {
  class InnerClass(age:Int,gender:String){
    private var _age:Int = age
    private var _gender:String = gender

    def getAge = _age
    def getGender = _gender

    def setAge(age:Int) = _age = age
    def setGender(gender:String) = _gender = gender
  }

  private val _name:String = name
  private var _in:InnerClass = new InnerClass(age, gender)
  var _in2:OutClass.Inner2Class = new OutClass.Inner2Class(school, major)

  def setAge(age:Int) = _in.setAge(age)
  def setGender(gender:String) = _in.setGender(gender)
  def setIn(in:InnerClass) = _in = in
  def setIn2(in2:OutClass.Inner2Class) = _in2 = in2

  override def toString: String = 
    s"${_name},${_in.getAge},${_in.getGender},${_in2._school},${_in2._major}"
}
object OutClass{
  class Inner2Class(school:String,major:String){
    val _school:String = school
    val _major:String = major
  }
}

val oc = new OutClass("henry",22,"male","南邮","通信")

oc.setAge(33)
oc.setGender("female")

val in = new oc.InnerClass(30, "female") // 外部类对象.内部类(...)
oc.setIn(in)
val in2 = new OutClass.Inner2Class("南信大","人工智能")
oc.setIn2(in2)

样例类

/*
	描述【不可变值】的对象
	样例类构造参数默认声明为 val,自动生成 getter
	样例类的构造参数若声明为 var,自动生成 getter & setter
	样例类自动生成伴生对象
	样例类自动实现的其他方法:toString,copy,equals,hashCode
	样例类伴生对象实现的方法:apply, unapply(用于模式匹配)
*/
// 普通类的模式匹配案例
case class Student(name:String, age:Int)	// 构造参数默认 val
case class Point(var x:Int,var y:Int)		// var 需要显式声明

val obj:Any = Student("henry",18)
val info = obj match {
    case Student(_,22) => "22"
    case Student(name,_) if name.startsWith("张") => "姓张"
    case Point(a,_) => s"$a" // 报错 cannot resolve symbol
}

// 追加伴生对象并实现 apply & unapply 之后,不再报错
object Point{
  def apply(x: Int, y: Int): Point = new Point(x, y)
  def unapply(arg: Point): Option[(Int, Int)] = Some((arg._x,arg._y))
}

枚举

/*
	单例对象通过继承 Enumeration 实现枚举创建,简单易用,但不可扩展
	通常用于定义一个有限取值范围的常量
*/
object WeekDay extends Enumeration {
  val MON = Value(0)
  val TUE = Value(1)
  val WEN = Value(2)
  val THU = Value(3)
  val FRI = Value(4)
  val SAT = Value(5)
  val SUN = Value(6)
}
val wd = WeekDay.WEN
val info = wd match {
    case WeekDay.MON => "星期一"
    case WeekDay.TUE => "星期二"
    case WeekDay.WEN => "星期三"
    case _ => "不需要"
}

泛型

/*
	类型参数化,主要用于集合
	不同于 Java 泛型被定义在 [] 中
	
*/

class GrandFather(name:String) {
  val _name:String = name
  override def toString: String = _name
}
object GrandFather{
  def apply(name: String): GrandFather = new GrandFather(name)
}

class Father(name:String) extends GrandFather(name:String) {}
object Father{
  def apply(name: String): Father = new Father(name)
}

class Son(name:String) extends Father(name:String) {}
object Son{
  def apply(name: String): Son = new Son(name)
}

class GrandSon(name:String) extends Son(name:String){}
object GrandSon{
  def apply(name: String): GrandSon = new GrandSon(name)
}

/*
	泛型边界定义
	上边界:T<:A	泛型为某个类型的子类
	下边界:T>:A	泛型为某个类型的父类
*/
class MyArray[T <: Father](items:T*) {
  def join(sep:String) = items.mkString(sep)
}
// Type GrandFather does not conform to 【 upper bound 】 Father of type parameter T
val arr:MyArray[GrandFather] = ...

class MyArray[T >: Son](items:T*) {
  def join(sep:String) = items.mkString(sep)
}
// Type GrandSon does not conform to 【 lower bound 】 Son of type parameter T
val arr:MyArray[GrandSon] = ...

/*
	型变:多态
	协变:[+T]		若A是B的子类,则 C[A]为C[B]的子类
	逆变:[-T]		若A是B的子类,则 C[B]为C[A]的子类
	不变:[T]		默认
*/
class MyArray[+T](items:T*) {
  def join(sep:String) = items.mkString(sep)
}
// Father 是 Son 的父类,则 MyArray[Father] 就是 MyArray[Son] 的父类
val arr:MyArray[Father] = new MyArray[Son](Son("henry"),Son("ariel"))

class MyArray[-T](items:T*) {
  def join(sep:String) = items.mkString(sep)
}
// Father 是 Son 的子类,则 MyArray[Son] 就是 MyArray[Father] 的子类
val arr:MyArray[Son] = new MyArray[Father](Son("henry"),Son("ariel"))

class MyArray[T](items:T*) {
  def join(sep:String) = items.mkString(sep)
}
// 所有泛型都必须为 Son
val arr:MyArray[Son] = new MyArray[Son](Son("henry"),Son("ariel"))

包与包对象

/*
 【包】
	包命名规则:字母、数字、下划线、点,不能以数字开头,在【一个类文件中可以定义多个并列的包】
	导包的不同方式
		import com.kgc.Person				方便使用类 Person
		import com.kgc._					方便使用 com.kgc 包中的所有类
		import com.kgc.Person._				方便使用类 Person 中的所有属性和方法
		import com.kgc.{Person=>PS,Book}	只导入包中 Person和Book,并将Person重命名为PS
	不同于Java
		import 导包语句可以出现在任意地方
		可以导入包、类、类成员
*/
// 单个文件多包结构:资源按包名语义分类存放,方便管理和使用
----------------------- Test.scala START ----------------------------
package cha03{
  import cha03.util.Sorts
  object PackageTest {
    def main(args: Array[String]): Unit = {
      val array: Array[Int] = Array(3, 1, 5, 4, 2)
      Sorts.insertSort(array)
      array.foreach(println)
    }
  }
}

package cha03.util{
  object Sorts{
    def insertSort(array: Array[Int]): Unit ={
      import scala.util.control.Breaks._
      for(i<- 1 until array.length){
        val t = array(i)
        var j = i-1
        breakable({
          while (j>=0){
            if(array(j)>t){
              array(j+1) = array(j)
            }else{
              break()
            }
            j-=1
          }
        })
        array(j+1) = t
      }
    }
  }
}
----------------------- Test.scala END ----------------------------

/*
 【包对象】
	包中可以包含:类、对象、特质...
	包对象可以包含:除了类、对象、特质外,还可以包含变量和方法
*/
package cha03{
  import cha03.util.Constants._
  import cha03.util.Constants.{DataFormat=>DF}
  
  object PackageTest {
    def main(args: Array[String]): Unit = {
      println(PI*2*2)
      println(getQuarter(5))
      val format: DF = DF(2024, 3, 29)
      println(format.stdYMD())
      println(format.stdFull())
      println(format.timestamp())
    }
  }
}
package cha03.util{
  import java.util.Calendar
  // 包对象
  package object Constants{
    // 变量
    val PI:Float = 3.14f
	// 方法
    def getQuarter(month:Int)=(month-1)/3+1
	// 类
    class DataFormat(
        year:Int,month:Int,day:Int,
        hour:Int,minute:Int,second:Int,
        millis:Int){
      private var _year:Int = year
      private var _month:Int = month
      private var _day:Int = day
      private var _hour:Int = hour
      private var _minute:Int = minute
      private var _second:Int = second
      private var _millis:Int = millis

      def this(year:Int,month:Int,day:Int){
        this(year,month,day,0,0,0,0)
      }

      def stdYMD():String = s"${_year}-${_month}-${_day}"
      def stdFull():String = s"${_year}-${_month}-${_day} ${_hour}:${_minute}:${_second}.${_millis}"
      def timestamp():Long = {
        val cld = Calendar.getInstance()
        cld.set(_year,_month,_day,_hour,_minute,_second)
        cld.set(Calendar.MILLISECOND,555)
        cld.getTimeInMillis
      }
    }
  }
  object DataFormat{
      def apply(year: Int, month: Int, day: Int, 
                hour: Int, minute: Int, second: Int, millis: Int): DataFormat 
      	= new DataFormat(year, month, day, hour, minute, second, millis)
      def apply(year: Int, month: Int, day: Int): DataFormat 
      	= new DataFormat(year, month, day)
  }
}

// 导包
import pack_name
import pack_name._
import pack_name.{A=>AS,B}
import pack_name.Class
import pack_name.Class.{PI,show}
import pack_name.Class._

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/569410.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

北京筑龙当选中招协第二届招标采购数字化专业委员会执行主任单位

4月18-19日&#xff0c;中国招标投标协会&#xff08;以下简称中招协&#xff09;2024年年会在宁波召开&#xff0c;北京筑龙作为中招协理事会员单位受邀出席会议。会议期间举行了“电子招标采购专业委员会换届会议暨第二届第一次工作会议”&#xff0c;北京筑龙当选第二届招标…

Leetcode 第 393 场周赛题解

Leetcode 第 393 场周赛题解 Leetcode 第 393 场周赛题解题目1&#xff1a;3114. 替换字符可以得到的最晚时间思路代码复杂度分析 题目2&#xff1a;3115. 质数的最大距离思路代码复杂度分析 题目3&#xff1a;3116. 单面值组合的第 K 小金额思路代码复杂度分析 题目4&#xff…

探索人工智能的边界:GPT 4.0与文心一言 4.0免费使用体验全揭秘!

探索人工智能的边界:GPT与文心一言免费试用体验全揭秘! 前言免费使用文心一言4.0的方法官方入口进入存在的问题免费使用文心一言4.0的方法免费使用GPT4.0的方法官方入口进入存在的问题免费使用GPT4.0的方法前言 未来已来,人工智能已经可以帮助人们完成许多工作了,不少工作…

【FX110网】股市、汇市一年有多少个交易日?

事实上&#xff0c;作为交易者&#xff0c;重要的是要了解并非每天都是交易日。虽然金融市场在大多数工作日开放交易&#xff0c;但在某些特定情况下无法进行交易。这些非交易日可能因各种原因而发生&#xff0c;包括节假日、周末和市场休市。 通过随时了解假期、交易时间表和市…

CSS3:border-image

<!DOCTYPE html> <html><head><meta charset"utf-8"> </head><body><p>原始图片</p><img src"./images/border1.png" alt""><p>一、</p><p>border: 27px solid transp…

qt5-入门-自定义委托-可编辑的TableModel与信号接收

参考&#xff1a; C GUI Programming with Qt 4, Second Edition 本地环境&#xff1a; win10专业版&#xff0c;64位&#xff0c;Qt5.12 上一篇&#xff1a; qt5-入门-自定义委托-简单例子_qt 委托-CSDN博客 https://blog.csdn.net/pxy7896/article/details/137234839 本篇重…

报名 | Qt汽车及工业行业解决方案及实战训练 深圳站(5月15日 星期三)

加入我们的Qt技术培训&#xff0c;探索跨平台应用开发的无限可能&#xff01;本次培训将深入Qt框架&#xff0c;涵盖从基础概念到高级功能的全方位知识&#xff0c;无论您是刚入门的新手还是希望提升技能的资深开发者&#xff0c;都能在此找到适合自己的学习路径。通过实践案例…

Docker 入门介绍及简单使用

Docker 的简单介绍 中文官网&#xff1a;Docker中文网 官网 英文官网&#xff1a;Docker: Accelerated Container Application Development Docker 是一个开源的应用容器引擎&#xff0c;它允许开发者打包应用及其依赖包到一个可移植的容器中&#xff0c;然后发布到任何流行的 …

齐护K210系列教程(八)_LCD显示图片

LCD显示图片 文章目录 LCD显示图片1&#xff0c;显示单张图片2&#xff0c;通过按键切换显示SD卡内的图片3&#xff0c;通过传感器切换图片4&#xff0c;画中画显示&#xff0c;并缩放5&#xff0c;课程资源 联系我们 AIstart 显示的图片的默认分辨率为&#xff1a;320*240 &am…

代码随想录算法训练营DAY36|C++贪心算法Part.5|435.无重叠区间、763.划分字母区间、56. 合并区间

文章目录 435.无重叠区间按右边界排序CPP代码 按左边界排序如何判断相邻区间是否重叠如何判断一下一个区间与当前相邻区间是否重叠总结CPP代码 763.划分字母区间思路伪代码实现CPP代码 56. 合并区间思路CPP代码 435.无重叠区间 力扣题目链接 文章链接&#xff1a;435.无重叠区间…

开发简易复用 SDK(项目加分项)

文章目录 开发 SDK新建项目修改pom文件删除启动类创建配置类复制之前的客户端新建spring.factories打包 开发 SDK 为什么要开发SDK。 减少代码的冗余提高代码的复用 如果实际项目中需要使用到该SDK&#xff0c;在pom.xml中注入就可以了。 类似于maven一样&#xff0c;把需要…

索引的最左匹配原则

索引的最左匹配原则 我们先创建一张测试表&#xff0c;表的两个字段用来创建联合索引 CREATE TABLE test(id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,col1 INT,col2 INT,col3 INT );CREATE INDEX idx_c1c2 ON test(col1, col2);现在我们就可以分析查询sql脚本了 1.使用联合索…

jasypt组件死锁bug案例分享

事故描述 1、上午9.55发布了一个Apollo动态配置参数&#xff1b; 2、片刻后&#xff0c;服务器接口开始出现大量的超时告警&#xff0c;似乎是某资源被耗尽不足分配&#xff1b; 3、正值业务请求高峰的上午十点&#xff08;平台上午10点会有一些活动会拉一波用户流量&#x…

Redis事务全解析:从MULTI到EXEC的操作指南!

【更多精彩内容,欢迎关注小米的微信公众号“软件求生”】 亲爱的粉丝朋友们,大家好!今天我们要讨论的主题是Redis的事务。Redis作为一款优秀的NoSQL数据库,凭借其高性能和灵活性广受欢迎。事务是Redis的一项关键功能,它为我们提供了一种在数据操作中确保一致性的机制。接…

【目标检测】FPN特征金字塔完整流程详解

学习视频&#xff1a;1.1.2 FPN结构详解 对比 可以看到FPN是自上而下、自下而上并且可以进行多尺度特征融合的的层级结构。 具体结构 1x1 conv: 对通道数进行调整&#xff0c;不同大小的特征图通道数不同&#xff0c;越高层次的特征图通道数越大&#xff0c;论文中使用256个1…

Linux-线程互斥和死锁

目录 一.线程互斥 1.1 进程线程间的互斥相关背景概念 1.2 互斥量mutex 二.互斥量的接口 2.1 初始化互斥量 2.2 销毁互斥量 2.3 互斥量加锁和解锁 2.4 改进后售票代码 三.死锁 3.1.什么是死锁&#xff1f; 3.2.死锁四个必要条件 3.3 避免死锁 一.线程互斥 1.1 进程…

【01-机器学习入门:理解Scikit-learn与Python的关系】

文章目录 前言Python与机器学习Scikit-learn简介Scikit-learn与Python的关系使用Scikit-learn进行机器学习结语前言 在当今的数据科学和人工智能领域,机器学习已经成为了一个不可或缺的组成部分。而对于那些刚刚踏入这一领域的新手来说,理解机器学习的基本概念和找到合适的工…

实施阶段(2024年4月)

【活动二】编程解决问题&#xff0c;二分查找法统计查字典次数。 任务要求&#xff1a;假设字典为1000页&#xff0c;若用二分法来翻到用户输入的具体指定的页数&#xff0c;则需要的最大查找次数为&#xff1f; 设计算法&#xff1a; 取总页码数据中间值&#xff0c;将待查数…

深入理解Linux文件系统和日志分析

目录 一.inode与block 1.inode与block概述 1.1.文件数据包括元信息与实际数据 1.2.文件存储在硬盘上&#xff0c;硬盘最小存储单位是“扇区”&#xff0c;每个扇区存储512字节 1.3.block&#xff08;块&#xff09; 1.4.inode&#xff08;索引节点&#xff09; 2.inode内…

统一SQL 支持Oracle CHAR和VARCHAR2 (size BYTE|CHAR)转换

统一SQL介绍 https://www.light-pg.com/docs/LTSQL/current/index.html 源和目标 源数据库&#xff1a;Oracle 目标数据库&#xff1a;Postgresql&#xff0c;TDSQL-MySQL&#xff0c;达梦8&#xff0c;LightDB-Oracle 操作目标 在Oracle中的CHAR和VARCHAR2数据类型&…
最新文章