Scala 04 —— Scala Puzzle 拓展

马肤
这是懒羊羊

Scala 04 —— Scala Puzzle 拓展,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,操作,li,进行,第1张

Scala 04 —— Scala Puzzle 拓展,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,操作,li,进行,第2张

Scala 04 —— Scala Puzzle 拓展

文章目录

  • Scala 04 —— Scala Puzzle 拓展
      • 一、占位符
      • 二、模式匹配的变量和常量模式
      • 三、继承 成员声明的位置
          • 结果
          • 初始化顺序分析
            • `BMember` 类
            • `BConstructor` 类
            • 四、缺省初始值与重载
            • 五、Scala的集合操作和集合类型保持一致性
                • 第一部分代码解释
                • 第二部分代码解释
                • 六、for和map的区别

                  一、占位符

                  val list1:List[Int] = List(1,2,3).map(_ + 1)
                  val list2:List[Int] = List(1,2,3).map(r => r + 1)
                  

                  在上面的例子中,两代码的返回结果其实是一样的,都是 List(2,3,4),而在第一行中的 _叫做占位符,可以让我们的代码更加简洁 但是这并不意味着使用 _ 和箭头函数是同样的结果

                  val list1:List[Int] = List(1,2,3).map{println("ss");_ + 1}
                  val list2:List[Int] = List(1,2,3).map{r => println("ss");r + 1}
                  

                  在上面的代码中,看起来运行的结果还是一样的,但是事实却不是这样的,当然 list1 和 list2的返回值是一样的,但是执行的过程中打印的结果却是不一样的, 第一行代码打印了一行 ss,第二行代码打印了三行 ss

                  为什么会有这样的不同?

                  Map函数的本质是对每个集合中的元素应用一个函数,第一个语句中函数的执行体只是_+1,第二个语句中函数的执行体是println("ss");r + 1。

                  二、模式匹配的变量和常量模式

                  • 变量模式:模式匹配的标识符是小写字母,作用是赋值

                    val (x,y) = (1,2)
                    
                  • 常量模式:模式匹配的标识符是大写字母,该常量必须是已赋值的,否则会报错,作用是判断

                    val (X,Y) = (1,2)// 报错
                    x match {
                      case PI => "圆周率"
                    }
                    

                    三、继承 成员声明的位置

                    trait A{
                      val audience:String
                      println("Hello " + audience)
                    }
                    class BMember (a:String = "World") extends A{
                      override val audience: String = a
                      println("I repeat:Hello " + audience)
                    }
                    class BConstructor(val audience:String = "World") extends A{
                      //该种方法声明的变量不会存在null的情况
                      println("I repeat:Hello " + audience)
                    }
                    new BMember("reader")
                    new BConstructor("reader")
                    
                    结果
                    Hello null
                    I repeat:Hello reader
                    Hello reader
                    I repeat:Hello reader
                    
                    初始化顺序分析
                    BMember 类
                    1. 调用构造器:当创建 BMember 的实例时,首先初始化父类 A。
                    2. 父类 A 的初始化:在 Scala 中,父类的构造代码块(包括字段的初始化和任何其他语句)首先被执行。在 A 中,audience 还未被 BMember 初始化,因此其值为 null(String 类型的默认值)。
                    3. 打印语句执行:打印 "Hello " + audience,由于 audience 还是 null,输出 Hello null。
                    4. 子类 BMember 的字段初始化:初始化 audience 为传入的参数 "reader"。
                    5. 子类中的打印语句:接着执行 BMember 中的打印语句,输出 "I repeat: Hello reader"。
                    BConstructor 类
                    1. 构造器参数:在 BConstructor 类中,audience 是通过构造器参数直接定义的。这意味着在调用父类 A 的构造器之前,audience 已经被初始化。
                    2. 父类 A 的初始化:由于 audience 已经初始化为 "reader",当父类 A 中的打印语句执行时,输出 "Hello reader"。
                    3. 子类中的打印语句:紧接着在 BConstructor 中,再次打印 "I repeat: Hello reader"。

                    总结:

                    一般来说,子类在初始化时会先初始化父类构造器构造出父类对象,因为子类可能有依赖于父类对象的属性或方法。

                    作为类字段被赋值,在父类构造器执行后才初始化;作为构造参数被赋值,在父类构造器执行前初始化。

                    四、缺省初始值与重载

                    trait A {
                      val foo: Int //缺省初始值,Boolean缺省初始值是false,Unit缺省初始值是()
                      def bar: Int = 10 //附初值的变量后面只能用override
                      println(s"In A:foo=$foo,bar=$bar") //0,0,0
                    }
                    class B extends A {
                      val foo: Int = 25
                      println(s"In B:foo=$foo,bar=$bar") //25,36,0
                    }
                    class C extends B {
                      override val foo: Int = 46 //当一个val被重载的时候,只能初始化一次
                      override def bar: Int = 100
                      println(s"In C:foo=$foo,bar=$bar") //25,36,99
                    }
                    new C()
                    /*
                    In A:foo=0,bar=100
                    In B:foo=0,bar=100
                    In C:foo=46,bar=100
                    */
                    
                    • 字段初始化顺序:像val foo:Int,字段初始化发生在构造器体执行之前,但超类的构造器(包括 println 语句)会在任何子类字段初始化之前执行。

                    • 方法动态绑定:像def bar:Int=5,Scala 会使用动态绑定来决定应该调用哪个版本的方法。即使在超类的构造器中,也会调用最终重写的方法版本(在 C 中为 100)。

                    • 字段重写:foo 在子类中被重写,但在超类和任何父类的构造器中引用这个字段时,它们看到的是其默认值(在赋值之前),直到子类自己的构造器赋予它新值。

                    • 当一个 val被重载,只能初始化一次

                      五、Scala的集合操作和集合类型保持一致性

                      def sumSizes(collections:Iterable[Iterable[_]]):Int = {
                        //      println(s"collections:$collections")
                        //      println(collections.map(_.size))
                        collections.map(_.size).sum
                      }
                      
                      第一部分代码解释
                      println(sumSizes(List(Set(1,2),List(3,4))))
                      

                      在这里,输入是List类型的,包含两个集合:一个Set和一个List。List映射(map)操作会返回一个新的List,其中包含每个子集合的大小:

                      • Set(1, 2)的大小为2(因为集合中不允许重复值)
                      • List(3, 4)的大小为2

                        因此,map(_.size)返回List(2, 2),其和为4。

                        第二部分代码解释
                        println(sumSizes(Set(List(1,2),Set(3,4))))
                        

                        这里输入是Set类型的。由于Set在map操作后仍保持Set类型,而且不允许重复值,它会影响结果:

                        • List(1, 2)的大小为2
                        • Set(3, 4)的大小也是2

                          由于结果Set不能有重复值,map(_.size)产生的结果是Set(2),其和为2,因为只有一个元素。

                          def sumSizes1(collections:Iterable[Iterable[_]]):Int = {
                            collections.toSeq.map(_.size).sum
                          }
                          

                          不管是什么集合类型,都将其转换成Seq

                          六、for和map的区别

                          val ys = for(Seq(x,y,z) case Seq(x,y,z) =x+y+z}
                          

                          当遇到Seq("g", "h")时,模式Seq(x, y, z)无法匹配只有两个元素的序列,因此Scala抛出了MatchError。

                          Scala 04 —— Scala Puzzle 拓展,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,操作,li,进行,第3张


文章版权声明:除非注明,否则均为VPS857原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复:表情:
评论列表 (暂无评论,0人围观)

还没有评论,来说两句吧...

目录[+]

取消
微信二维码
微信二维码
支付宝二维码