1:Scala之函数式编程学习笔记:

:Scala函数式编程学习:
1.1:Scala定义一个简单的类,包含field以及方法,创建类的对象,并且调用其方法:
class User { private var name = "张三";
def hello(): Unit ={
println("hello : " + name)
}
//注:如果定义方法时不带括号,则调用的时候也不可以加括号,否则报错。
def getName = name;
}
//创建一个object来调用练习的实体类对象.
object Hello { def main(args: Array[String]): Unit = {
var user = new User;
user.hello();
println(user.getName)
}
}
:Scala中field字段的getter和setter详解教程:
2.1:定义不带private的var field,此时scala生成的面向jvm的类时,会定义为Private的name字段,并提供public的getter和setter的方法:
class User { var name = "张三";
var age = ;
}
//创建一个object来调用练习的实体类对象.
object Hello { def main(args: Array[String]): Unit = {
var user = new User;
user.name="李四";
user.age=;
println(user.name + " " + user.age)
}
} 2.2:如果使用private修饰field,则生成的getter和setter也是private的:
class User { private var name = "张三";
private var age = ;
}
//创建一个object来调用练习的实体类对象.
object Hello { def main(args: Array[String]): Unit = {
var user = new User;
//如果使用private修饰field,则生成的getter和setter也是private的,所以调用会报错。
//println(user.name + " " + user.age)
}
}
2.3:如果定义val field,则只会生成getter方法:
class User { val name = "张三";
val age = ;
}
//创建一个object来调用练习的实体类对象.
object Hello { def main(args: Array[String]): Unit = {
var user = new User;
//如果定义val field,则只会生成getter方法。所以调用setter方法会报错的。
//user.name_="张三";
println(user.name + " " + user.age)
}
}
2.4:如果不希望生成setter和getter方法,则将field声明为private[this]:
class User { private[this] var name = "张三";
private[this] var age = ;
}
//创建一个object来调用练习的实体类对象.
object Hello { def main(args: Array[String]): Unit = {
var user = new User;
//则将field声明为private[this],不生成setter和getter方法。所以调用setter和getter方法报错
//user.name_="张三";
//println(user.name + " " + user.age)
}
}
2.5:调用getter和setter方法,分别叫做name和name_=
class User { var name = "张三";
var age = ;
}
//创建一个object来调用练习的实体类对象.
object Hello { def main(args: Array[String]): Unit = {
var user = new User;
println(user.name + " " + user.age)
//调用setter方法来修改值
user.name="李四";
println(user.name + " " + user.age)
}
}
2.6:如果只是希望拥有简单的getter和setter方法,那么就按照scala提供的语法规则,根据需求为field选择合适的修饰符就好:var,val,private,private[this];
注意:如果希望能够自己对gettter和setter进行控制,则可以自定义getter和setter方法,自定义setter方法的时候一定要注意scala的语法限制,签名,=,参数间不能有空格
class User {
var name : String = "张三";
var age : Int = ;
def getName = "my name is : " + name;
def setName_=(newName : String): Unit ={
println("不可以修改你的姓名。")
}
}
//创建一个object来调用练习的实体类对象.
object Hello { def main(args: Array[String]): Unit = {
var user = new User;
user.name="李思思"
println(user.getName + " " + user.age) }
}
2.7:如果不希望field有setter方法,则可以定义为val,但是此时就再也不能更改field的值了。如果希望能够仅仅暴漏出一个getter方法,并且还能通过某些方法更改field的值,那么需要综合使用private以及自定义getter方法。此时,由于field是private的,所以setter和getter都是private的,对外界没有暴漏,自己可以实现修改field值的方法;自己可以覆盖getter方法。
class User { private var myName : String = "张三";
def updateName(newName : String): Unit ={
if(newName == "李四"){
myName = newName;
}else{
println("此值不可以修改")
}
} def name = "you name is :" + myName;
}
//创建一个object来调用练习的实体类对象.
object Hello { def main(args: Array[String]): Unit = {
var user = new User;
user.updateName("李四");
println(user.name) }
}
2.8:如果将field使用private来修饰,那么代表这个field是类私有的,在类的方法中,可以直接访问类的其他对象的private field;这种情况下,如果不希望field被其他对象访问到,那么可以使用private[this],意味着对象私有的field,只有本对象内可以访问到。
class User { private[this] var myAge : Int = ;
def age_=(newAge : Int): Unit ={
if(newAge > ){
myAge = newAge;
}else println("不合法的年龄")
} def age = myAge;
//使用private[this],意味着对象私有的field,只有本对象内可以访问到。
//def orderAge(user : User) ={
//myAge > user.myAge;
//}
}
//创建一个object来调用练习的实体类对象.
object Hello { def main(args: Array[String]): Unit = {
var user = new User;
user.age_=();
println(user.age)
user.age = ;
println(user.age)
var user2 = new User;
user2.age_=();
if(user2.orderAge(user)){
println("user2 大于 user")
}else{
println("user2 小于 user")
}
}
}
2.9:Scala的getter和setter方法的命名与java是不同的,是field和field_=的方式,如果要让scala自动生成java风格的getter和setter方法,只要给field添加@BeanProperty注解即可;此时会生成4个方法,name:String,name_=(newName:String):Unit,getName():String,setName_(newValue:String):Unit;
class User { @BeanProperty var name : String = _;
}
//创建一个object来调用练习的实体类对象.
object Hello { def main(args: Array[String]): Unit = {
var user = new User;
user.setName("张三");
println(user.getName);
user.name_=("李思思");
println(user.name)
}
}
:Scala中constructor详解:
3.1:Scala中,可以给类定义多个辅助constructor,类似于java中的构造函数重载;辅助constructor之间可以互相调用,而且必须第一行调用主constructor
class User { @BeanProperty var name : String = _;
@BeanProperty var age : Int =_; def this(name: String){
this();
this.name = name;
}
def this(name : String, age :Int){
this(name);
this.age = age;
}
}
//创建一个object来调用练习的实体类对象.
object Hello { def main(args: Array[String]): Unit = {
var user = new User;
var user2 = new User("张三");
var user3 = new User("李四",);
}
}
3.2:Scala中,主构造constructor是与类名放到一起的,与java不同。而且类中,没有定义在任何方法或者是代码块之中的代码,就是主constructor的代码,这是感觉没有java那么清晰;
注意:如果主constructor传入的参数什么修饰都没有,比如name:String。那么类内部的方法使用到了,则会声明为private[this] name,否则没有该field,就只能被constructor代码使用而已。
class User(name : String, age : Int) {
println("you name is :" + name + ", you age is : "+ age) var id : Int = _;
}
//创建一个object来调用练习的实体类对象.
object Hello { def main(args: Array[String]): Unit = {
var user = new User("张三",);
user.id_=();
println("you id is :" +user.id) }
}
3.3:主构造方法constructor方法中还可以通过使用默认参数,来给参数默认的值:
class User(val name : String="李思思", age : Int = ) {
println("you name is :" + name + ", you age is : "+ age) var id : Int = _;
}
//创建一个object来调用练习的实体类对象.
object Hello { def main(args: Array[String]): Unit = {
var user = new User();
user.id_=();
println("you id is :" +user.id) }
}
:Scala中内部类的介绍:
4.1:在Scala中,同样可以在类中定义内部类,但是与java不同的是,每个外部类的对象的内部类,都是不同的类:
class User { class Student(val name : String){};
val students = new ArrayBuffer[Student];
def getStudent(name : String) = {
new Student(name);
}
}
//创建一个object来调用练习的实体类对象.
object Hello { def main(args: Array[String]): Unit = {
val user1 = new User();
val stu = user1.getStudent("张三");
println(stu)
user1.students += stu; var user2 = new User;
var stu2 = user2.getStudent("李四");
println(stu2)
//下面这一行报错,好好体会一下
//user1.students += stu2;
}
}

2:Scala之Object对象学习笔记:

:Object对象:
1.1:object对象,相当于class的单个实例,通常在里面放一些静态的field或者method;第一次调用object的方法时候,就会执行object的constructor构造方法,也就是Object内部不在method中的代码;但是Object不能定义接受参数的constructor;object通常用于作为单例模式的实现,或者放class的静态成员,比如工具方法;
注意:object的constructor只会在其第一次被调用的时候执行一次,以后再次调用就不会执行constructor了。
object Hello { private val name = "张三";
println("this is object Hello");
def show(): Unit ={
println("一步一个脚印");
}
def getName = name;
def main(args: Array[String]): Unit = {
show()
println(getName);
println(Hello.getName)
}
}

3:Scala之伴生对象学习笔记:

:伴生对象,如果有一个class,还有一个与class同名的Object,那么就称这个object是class的伴生对象,class是object的伴生类;伴生类与伴生对象必须存放在一个.scala文件之中;伴生类与伴生对象,最大的特点就是在于,互相可以访问private field;

4:Scala之继承学习笔记:

:让object继承抽象类:
1.1:object的功能其实和class类似,除了不能定义接受参数的constructor之外,object也可以继承抽象类,并且覆盖抽象类中的方法:
abstract class User(val name : String) { def hello(name : String): Unit ={
//println("you name is : "+ name)
}
}
//创建一个Object继承User类
object UserImpl extends User("张三"){ override def hello (name: String): Unit = {
println("you name is :" + name)
}
}
//创建一个Object来进行测试
object Test { def main(args: Array[String]): Unit = {
//object的功能其实和class类似,除了不能定义接受参数的constructor之外
var ui = UserImpl;
//方式一
ui.hello("李四");
//方式二
UserImpl.hello("王五");
}
}
:Apply方法,object中非常重要的一个特殊方法,就是apply方法。通常在伴生对象中实现apply方法,并在其中实现构造伴生类的对象的功能。而创建伴生类的对象时,通常不会使用new Class的方式,而是使用Class()的方式,隐式的调用伴生对象得到apply方法,这样会让对象创建更加简洁:
2.1:比如,Array类的伴生对象的apply方法就实现了接受可变数量的参数,并且创建一个Array对象的功能:
var arr = Array(,,,,,,,,);
2.2:比如,定义自己的伴生类和伴生对象:
class Person(val name : String) { }
//创建伴生对象
object Person{
def apply(name : String) = new Person(name)
}
//创建Object进行测试
object Test { def main(args: Array[String]): Unit = {
val p1 = new Person("张三");
println(p1.name);
val p2 = Person("李思思");
println(p2.name);
}
}
:main方法,就如同java中,如果要运行一个程序,必须编写一个包含main方法类一样,在scala中,如果想要运行一个应用程序,那么必须有一个main方法,作为入口;
3.1:注意:scala中的main方法定义为def main(args: Array[String]): Unit = {}。而且必须定义在object中;
App Trait的工作原理,App Trait继承自DelayedInit Trait,scalac命令进行编译时候,会把继承App Trait的object的construtcor代码都放到DelayedInit Trait的delayedInit方法中执行; object Test { def main(args: Array[String]): Unit = { }
}
3.2:除了自己实现main方法以外,还可以继承App Trait,然后将需要在main方法中运行的代码,直接作为Object的construstor代码。而且用args可以接受传入的参数:
object Test extends App{ if(args.length > ){
println("hello : " + args())
}else println("hello 你妹啊 hello.")
}
:用object来实现枚举功能:
4.1:scala没有直接提供类似于java中的Enum这样的枚举特性,如果要实现枚举,则需要用Object继承Enumeration类,并且调用value方法来初始化枚举值:
object Season extends Enumeration{ val SPRING,SUMMER,AUTUMN,WINTER = Value;
}
4.2:还可以通过value传入枚举值的id和name,通过id和toString可以获取,还可以通过id和name来查找枚举值:
object Season extends Enumeration{ // val SPRING,SUMMER,AUTUMN,WINTER = Value;
val SPRING = Value(,"spring");
val SUMMER = Value(,"summer");
val AUTUMN = Value(,"autumn");
val WINTER = Value(,"winter"); def main (args: Array[String]): Unit = {
println(Season());
println(Season.withName("spring"));
}
}
4.3:使用枚举object.values可以遍历枚举值:
object Season extends Enumeration{ //val SPRING,SUMMER,AUTUMN,WINTER = Value;
val SPRING = Value(,"spring");
val SUMMER = Value(,"summer");
val AUTUMN = Value(,"autumn");
val WINTER = Value(,"winter"); def main (args: Array[String]): Unit = {
for(i <- Season.values){
println(i)
}
}
}
5:Scala中,让子类继承父类,与Java一样,也是使用extends关键字;
    5.1:继承就代表,子类可以从父类继承父类的field和method,然后子类可以在自己内部放入父类没有的field或者method;子类拥有特有的field和method,使用继承可以有效的复用代码。
        class Person {           private var name : String = "张三";
          def getName = name;
          def setName_=(name : String): Unit ={
            println("private修改的字段,生成的setter和getter也是私有的。")
          }
        }
        //创建一个Student类来继承Person类:
        class Student extends Person{           private  var score : Int = 60;
          def getScore = score;
          def setScore_=(score : Int): Unit ={
            println("private修改的字段,生成的setter和getter也是私有的。")
          }
        }
        //创建一个Object来调用创建的Student或者Person类:
        object HelloWorld {           def main(args: Array[String]): Unit = {
            var student = new Student();
            println("my name is : " + student.getName + ", and my score is : " + student.getScore);
          }
        }
    5.2:子类可以覆盖父类的field和method,但是如果父类用final修饰,field和method用final修饰,则该类是无法被继承的,field和method是无法被覆盖的。
        //父类用final修饰
        final class Person {           private var name : String = "张三";
          def getName = name;
          def setName_=(name : String): Unit ={
            println("private修改的字段,生成的setter和getter也是私有的。")
          }
        }
        //创建一个Student类来继承Person类:
        class Student extends Person{               private  var score : Int = 60;
              def getScore = score;
              def setScore_=(score : Int): Unit ={
                println("private修改的字段,生成的setter和getter也是私有的。")
              }
            }
        //创建一个Object来调用创建的Student或者Person类:
        object HelloWorld {           def main(args: Array[String]): Unit = {
            var student = new Student();
            //父类用final修饰,则该类是无法被继承的,所以下面会报错
            //println("my name is : " + student.getName + ", and my score is : " + student.getScore);
          }
        }
6:Scala中的override和super:
    6.1:Scala中,如果子类要覆盖一个父类中的非抽象方法,则必须使用override关键字;override关键字可以帮助我们尽早的发现代码里面的错误,比如,override修改的父类方法的方法名我们拼写错误了,比如要覆盖的父类方法的参数我们写错了等等。此外,在子类覆盖父类方法以后,如果我们在子类中就要调用父类的被覆盖的方法呢?那就可以使用super关键字,现实的指定要调用父类的方法。
        class Person {           private var name : String = "张三";
          def getName = name;
          def setName_=(name : String): Unit ={
            println("private修改的字段,生成的setter和getter也是私有的。")
          }
        }
        //创建一个Student类来继承Person类:
        class Student extends Person{               private  var score : Int = 60;
              def getScore = score;
              def setScore_=(score : Int): Unit ={
                println("private修改的字段,生成的setter和getter也是私有的。")
              }
              //方法的覆盖,使用关键词override和super
              override def getName: String = "Student类继承Person,且覆盖getName方法:" + super.getName;
            }
        //创建一个Object来调用创建的Student或者Person类:
        object HelloWorld {           def main(args: Array[String]): Unit = {
            var student = new Student();
            println("my name is : " + student.getName + ", and my score is : " + student.getScore);
          }
        }
    6.2:Scala中,子类可以覆盖父类的val field,而且子类的val field还可以覆盖父类的val field的getter方法;只要在子类中使用override关键字即可;
        class Person {           val name : String = "张三";
          def age : Int = 0;
        }
        //创建一个Student类来继承Person类:    
        class Student extends Person{           override val name : String = "李四";           override val age : Int = 20;
        }    
        //创建一个Object来调用创建的Student或者Person类:
        object HelloWorld {           def main(args: Array[String]): Unit = {
            var student = new Student();
            println("my name is : " + student.name +   ",my age is :" + student.age);
          }
        }
7:isInstanceOf和asInstanceOf,如果我们创建了子类的对象,但是又将其赋予了父类类型的变量。则在后续的程序中,我们又需要将父类类型的变量转换为子类类型的变量。首先,需要使用isInstanceOf判断对象是否是指定类的对象,如果是的话,则可以使用asInstanceOf将对象转换为指定类型。
    注意:如果对象是null,则isInstanceOf一定返回false,asInstanceOf一定返回null;
         如果没有用isInstanceOf先判断对象是否为指定类的实例,就直接用asInstanceOf转换,则可能会抛出异常;
        class Person {           var name : String = "张三";
          var age : Int = 20;
        }
        //创建一个Student类来继承Person类:    
        class Student extends Person{           var sex : String ="男";         }
        //创建一个Object来调用创建的Student或者Person类:
        object HelloWorld {           def main(args: Array[String]): Unit = {
            //父类的变量引用了子类的对象.
            val p : Person = new Student;
            var s : Student = null;
            //注意是[]不是(),否则报错。
            if(p.isInstanceOf[Student]){
              s = p.asInstanceOf[Student];
            }
            println(" my name is :"+ s.name + " ,my age is :" + s.age)
          }
        }
8:getClass和classOf,isInstanceOf只能判断出对象是否是指定类以及其子类的对象,而不能精确判断出,对象就是指定类的对象。如果要求精确的判断对象就是指定类的对象,那么只能使用使用getClass和classOf了。
    用法如下所示:
        对象.getClass可以精确获取对象的类,classOf[类]可以精确获取类没然后使用==操作符即可判断:    
        class Student extends Person{           var sex : String ="男";
        }
        //创建一个Student类来继承Person类:    
        class Person {           var name : String = "张三";
          var age : Int = 20;
        }
        //创建一个Object来调用创建的Student或者Person类:
        object HelloWorld {           def main(args: Array[String]): Unit = {
            //父类的变量引用了子类的对象.
            val p : Person = new Student;
            var s : Student = null;
            //注意是[]不是(),否则报错。
            if(p.isInstanceOf[Student]){
              s = p.asInstanceOf[Student];
            }
            println("======================================================================")
            //注意,isInstanceOf不可以精确判断是子类还是父类的。
            if(p.isInstanceOf[Person] && p.isInstanceOf[Student]){
              println("0:p指向了Person,也指向了Student");
            }
            println("======================================================================")
            println(" my name is :"+ s.name + " ,my age is :" + s.age)
            if(p.getClass == classOf[Person]){
              //p指向的是Student;
              println("1:getClass的用法:" + p.getClass + ",classOf的用法:" + classOf[Person]);
            }
            println("======================================================================")
            if(p.getClass == classOf[Student]){
              println("2:getClass的用法:" + p.getClass + ",classOf的用法:" + classOf[Student]);
            }
            println("======================================================================")
            val p2 : Person = new Person;
            if(p2.getClass == classOf[Person]){
              //p2指向的是Person;
              println("3:getClass的用法:" + p2.getClass + ",classOf的用法:" + classOf[Person]);
            }
          }
        }
9:使用模式匹配进行类型判断:
    9.1:在实际开发中,比如Spark的源码中,大量的地方都是使用了模式匹配的方式进行类型的判断,这种方式更加的简洁明了,而且代码的维护性和可扩展性也很高。
        使用模式匹配,功能性上来说,与instanceOf一样,也是判断主要是该类以及该类的子类的对象即可,不是精确判断的:
        class Student extends Person{           var sex : String ="男";
        }
        //创建一个Student类来继承Person类:    
        class Person {           var name : String = "张三";
          var age : Int = 20;
        }
        //创建一个Object来调用创建的Student或者Person类:
        object HelloWorld {           def main(args: Array[String]): Unit = {
            //父类的变量引用了子类的对象.
            val p : Person = new Student;             //模式匹配
            p match {
              case person : Person => println("It is Person class");
              case student : Student => println("It is Student class");
              case _ => println("不知道是什么类型的.");
            }
          }
        }
10:Protected关键字,跟java一样,scala中同样可以使用protected关键字来修饰field和method,这样在子类中就不需要super关键字,直接就可以访问field和method;
    10.1:注意:还可以使用protected[this],则只能在当前子类对象中访问父类的field和method,无法通过其他子类对象访问父类的field和method;
        class Person {           protected var name : String = "张三";
          protected[this] var age : Int = 20;
        }
        //创建一个Student类来继承Person类:    
        class Student extends Person{           var sex : String ="男";
          def showPerson(): Unit ={
            println("my name is : " + name);
          }
          def makeFriends(s : Student): Unit ={
            //还可以使用protected(this)则只能在当前子类对象中访问父类的field和method,
            //无法通过其他子类对象访问父类的field和method;
            //下面的s.age会报错的。protected[this] var age : Int = 20;
            //println("my age is : " + age  + ",you age is : " + s.age);
          }
        }
11:调用父类的constructor,在scala中,每个类可以有一个主constructor和任意多个辅助constructor,而每个辅助constructor的第一行都必须是调用其他辅助constructor或者是主constructor;因此子类的辅助constructor是一定不可能直接调用父类的constructor的;
    注意:只能在子类的主constructor中调用父类的constructor,以下这种语法,就是通过子类的主构造函数来调用父类的构造函数;如果是父类中接受的参数,比如name和age,子类中接受时,就不要用任何val或者var来修饰了,否则会认为是子类要覆盖父类的field;
        class Person(val name : String,val age : Int) {         }
        //创建一个Student类来继承Person类:        
        class Student(name : String,age : Int,var score : Int) extends Person(name,age){           def this(name : String){
            this(name,0,0);
          }
          def this(age : Int){
            this("张三",age,0);
          }
        }
        //创建一个Student类来继承Person类:    
        object HelloWorld {           def main(args: Array[String]): Unit = {
            var student = new Student("李思思",22,100);
            println(student.name + " "  + student.age + " " + student.score)
            var student2 = new Student("王五");
            println(student2.name + " "  + student2.age + " " + student2.score)
            var student3 = new Student(20);
            println(student3.name + " "  + student3.age + " " + student3.score)           }
        }
12:匿名子类,在Scala中,匿名子类是非常常见,而且非常强大的。Spark的源码中也大量使用了这种匿名子类。
    匿名子类,也就是说,可以定义一个类的没有名称的子类,并且直接创建其对象,然后将对象的引用赋予一个变量。之后甚至可以将该匿名子类的对象传递给其他函数。
        class Person(protected val name : String) {           def hello()= "hello, I am :" + name;
        }
        //创建一个Student类来继承Person类:    
        object HelloWorld {           def main(args: Array[String]): Unit = {
            //匿名内部类
            var p = new Person("张三"){
              override def hello(): String = "匿名内部类,hello :" + name;
            }
            //调用
            println(p.hello());
          }
        }
13:抽象类,如果在父类中,有某些方法无法立即实现,而需要依赖不同的子类来覆盖,重写实现自己不同的方法实现。此时可以将父类中的这些方法不给出具体的实现,只有方法签名,这种方法就是抽象方法;
    13.1:注意:一个类中如果有一个抽象方法,那么类就必须用abstract来声明为抽象类,此时抽象类是不可以实例化的。
        在子类中覆盖抽象类的抽象方法时,不需要使用override关键字;
        abstract class Person(val name : String) {           def hello() : Unit;
        }
        //创建一个Student类来继承Person类:    
        class Student(name : String) extends  Person(name){           override def hello(): Unit = println("hello : " + name);
        }
        //创建一个Student类来继承Person类:
        object HelloWorld {           def main(args: Array[String]): Unit = {
            var student = new Student("张三")
            student.hello()
          }
        }
    13.2:抽象field,如果在父类中,定义了field,但是没有给出原始值,则此field为抽象field;
         抽象field意味着,scala会根据自己的规则,为var或者val类型的field生成对应的getter和setter方法,但是父类中是没有该field的。
         子类必须覆盖field,以定义自己的具体field,并且覆盖抽象field,不需要使用override关键字;
        abstract class Person {           val name : String;
        }    
        //创建一个Student类来继承Person类:    
        class Student extends  Person{           val name : String= "张三";
        }
        //创建一个Student类来继承Person类:    
        object HelloWorld {           def main(args: Array[String]): Unit = {
            var student = new Student
            println(student.name)
          }
        }

5:Scala之面向对象编程之Trait学习笔记:

:trait基础知识:
1.1:将trait作为接口使用:
a、Scala中的trait是一种特殊的概念,首先我们可以将trait作为接口来使用,此时的trait就与Java中的接口非常类似;
b、在trait中可以定义抽象方法,就与抽象类中的抽象方法一样,只要不给出方法的具体体现即可;
c、类可以使用extends关键字来继承trait,注意,这里不是implement,而是extends,在scala中没有implmemts的概念, 无论继承还是trait,统一都是extends;
d、类继承trait后,必须实现其中的抽象方法,实现时候不需要使用override关键字;
e、scala不支持对类进行多继承,但是支持多重继承trait,使用with关键字即可;
trait Person { def hello(name : String);
}
//定义一个MakeFriends的trait
trait MakeFriends { def makeFriends(friend: Friend);
}
//定义一个类来继承上面两个trait
class Friend(val name : String) extends Person with MakeFriends with Cloneable with Serializable{ def hello(name: String) = println("my name is : " +name) def makeFriends(friend: Friend) = println("hello,my name is : " + name + ",your name is :" + friend.name);
}
//定义一个object来测试实现的类
object HelloWorld { def main(args: Array[String]): Unit = {
var friend = new Friend("张三");
var friend2 = new Friend("李四");
friend.hello("李四");
friend.makeFriends(friend2);
}
}
1.2:在trait中定义具体方法:
Scala中的trait可以不是只定义抽象方法,还可以定义具体方法,此时trait更像是包含了通用工具方法的东西,有一个专有的名词来形容这种情况,就是说trait的功能混入了类。举例来说,trait中可以包含一些很多类都通用的功能方法,比如打印日志等等,Spark中就使用了trait来定义了通用的日志打印方法:
trait Logger { def log(message : String) = println(message);
}
//定义一个类来实现trait接口
        class User(val name : String) extends Logger{           def makeFriends(user: User): Unit ={
            println("hello, i am " + name + " i am nice to meet you :" + user.name);
            log("makeFriends logger User[name="+user.name+"]");
          }
        }
        //定义一个object来测试实现的类
        object HelloWorld {
        
        def main(args: Array[String]): Unit = {
            val user = new User("张三");
            val user2 = new User("李思思");
            user.makeFriends(user2);
          }
        } 1.3:在trait中定义具体字段:
  Scala中的triat可以定义具体field,此时继承triat的类就自动获得了triat中定义的field,但是这种获取field的方式与继承class不同:如果是继承class获取的field,实际是定义在父类中的,而继承triat获取的field,就直接被添加到了类中。
        trait Person {           def hello();
          //定义一个field
          val eyeNum : Int =2;
        }
        //定义一个类来实现trait接口
        class Friend(val name : String) extends Person{           def hello() = println("my name is : " +name + ",and i have : " +eyeNum + "eyes");         }
        //定义一个object来测试实现的类
        object HelloWorld {           def main(args: Array[String]): Unit = {
            var friend = new Friend("张三");
            friend.hello();
          }
        }
1.4:在trait中定义抽象字段:
  Scala中的Triat可以定义抽象field,而Triat中的具体方法则可以基于抽象field来编写,但是继承Triat的类,则必须覆盖抽象field,提供具体的值:
        trait Person {           //定义一个抽象的field
          val msg : String;
          //Triat中的具体方法则可以基于抽象field来编写
          def hello(name : String) = println(msg + " ," + name);
        }
        //定义一个类来实现trait接口
        class Friend(val name : String) extends Person{
          //但是继承Triat的类,则必须覆盖抽象field,提供具体的值;
          val msg : String = "hello";
          def makeFriends(p : Person)={
            hello(name)
            println("my name is : " + name,",and i want to make friends with you.")
          }
        }
        //定义一个object来测试实现的类
        object HelloWorld {           def main(args: Array[String]): Unit = {
            var friend = new Friend("张三");
            var friend2 = new Friend("张三");
            friend.makeFriends(friend2)
          }
        }
:trait高级知识:
2.1:位实例对象混入trait:
  有时候,我们可以在创建类的对象的时候,指定该对象混入某个trait,这样,就只有这个对象混入该trait的方法,而类的其他对象则没有:
        import scala.util.logging.Logged         trait MyLogged extends Logged{           override def log(msg: String): Unit = {
            println("log : " + msg);
          }
        }
        //定义一个类来实现trait接口
        import scala.util.logging.Logged         class Person(name : String) extends Logged{
          def hello(): Unit ={
            println("hi , i am is :" + name);
          }
          log("hello is invoked");
        }
        //定义一个object来测试实现的类
        object Object {           def main(args: Array[String]): Unit = {
            var person1 = new Person("张三");
            person1.hello();
            var person2 = new Person("李思思") with MyLogged;
            person2.hello()
          }
        }
2.2:trait调用链:
  a、Scala中支持让类继承多个Trait后,依次调用多个trait中的同一个方法,只要让多个trait的同一个方法中,在最后都执行super方法即可;
        b、类中调用多个trait中都有的这个方法时,首先会从最右边的trait的方法开始执行,然后依次往左执行,形成一个调用链条;
        c、这种特性非常强大,其实就相当于设计模式中的责任链模式的一种具体实现依赖;
        trait Handler {           def handler(data : String){}
        }
        //定义一个trait来实现trait接口
        trait DataValidHandler extends Handler{           override def handler(data: String): Unit = {
            println("check data : " + data);
            super.handler(data)
          }
        }
        //定义一个trait来实现trait接口
        trait SignatureValidHandler extends Handler{           override def handler(data: String): Unit = {
            println("signature : " + data)
            super.handler(data)
          }
        }
        //定义一个类来实现trait接口
        class Person(val name : String) extends SignatureValidHandler with DataValidHandler{           def hello(): Unit ={
            println("hello :" + name);
            handler(name);
          }
        }
        //定义一个object来测试实现的类
        object Object {           def main(args: Array[String]): Unit = {
            val p1 = new Person("张三");
            p1.hello();
          }
        }
2.3:在trait中覆盖抽象方法【注意语法】:
  在Trait中,是可以覆盖父trait的抽象方法的。但是覆盖时,如果使用了super.方法的代码,则无法通过编译。因为super.方法就会去掉用父trait的抽象方法,此时子trait的该方法还是会被认为是抽象的。此时如果要通过编译,就得给子trait的方法加上abstract override修饰:
        trait MyLogged extends Logged{           abstract override def log(msg: String): Unit = {
            super.log(msg)
          }
        }
2.4:混合使用trait的具体方法和抽象方法:
  trait Valid {           def getName : String;
          def valid : Boolean = {
            getName == "张三";
          }
        }
        //定义一个类来实现trait接口
        class Person(val name : String) extends Valid{           println(valid)           def getName = name;
        }
        //定义一个object来测试实现的类
        object Object {           def main(args: Array[String]): Unit = {
            var p1 = new Person("张三");           }
        }
2.5:trait的构造机制:
  在Scala中,trait也是有构造方法的,也就是trait中的,不包含在任何方法中的代码。而继承了trait的类的构造机制如下所示:
        a、父类的构造函数执行。
        b、trait的构造代码执行,多个trait从坐到右依次执行。
        c、构造trait的时候会先构造父类trait,如果多个trait继承同一个父trait,则父trait只会构造一次。
        d、所有trait构造完毕以后,子类的构造函数执行。
        trait Logger {           println("logger constructor")
        }
        //定义一个trait来实现trait接口
        trait Mylogger extends Logger{           println("Mylogger constructor")
        }    
        //定义一个trait来实现trait接口
        trait TimeLogger extends Logger{           println("TimeLogger constructor");
        }
        //定义一个class
        class Person{
            
          println("person construcotr")
        }
        //定义一个class继承类和trait
        class Student extends Person with Mylogger with TimeLogger{           println("Student constructor")
        }
        //定义一个object来测试实现的类
        object Object {           def main(args: Array[String]): Unit = {
            val s1 = new Student();
          }
        }
2.6:trait字段的初始化:
  在Scala中,trait也是有构造方法的,也就是trait中的,不包含在任何方法中的代码。而继承了trait的类的构造机制如下所示:
        a、父类的构造函数执行。
        b、trait的构造代码执行,多个trait从坐到右依次执行。
        c、构造trait的时候会先构造父类trait,如果多个trait继承同一个父trait,则父trait只会构造一次。
        d、所有trait构造完毕以后,子类的构造函数执行。
        trait Logger {           println("logger constructor")
        }
        //定义一个trait来实现trait接口
        trait Mylogger extends Logger{           println("Mylogger constructor")
        }    
        //定义一个trait来实现trait接口
        trait TimeLogger extends Logger{           println("TimeLogger constructor");
        }
        //定义一个class
        class Person{
            
          println("person construcotr")
        }
        //定义一个class继承类和trait
        class Student extends Person with Mylogger with TimeLogger{           println("Student constructor")
        }
        //定义一个object来测试实现的类
        object Object {           def main(args: Array[String]): Unit = {
            val s1 = new Student();           }
        }
2.7:让trait继承类:
   在Scala中,trait是没有接受参数的构造函数的,这是trait与class的唯一区别,但是如果需求就是要trait能够对field进行初始化,那么只能使用Scala中非常特殊的一种高级特性--提前定义:
        //1:第一种方式实现:
        trait Hello {           val msg : String;
          println(msg.toString);
        }
        //定义一个class继承类和trait
        class Person extends {           val msg : String = "init";
        }with Hello{}
        //定义一个object来测试实现的类
        object Object {           def main(args: Array[String]): Unit = {
            var p1 = new Person();
          }
        }
        //2:第二种方式实现:
        trait Hello {           lazy val msg : String = null;
          println(msg.toString);
        }
        //定义一个class继承类和trait
        class Person extends Hello{           override lazy val msg: String = "init"
        }
        //定义一个object来测试实现的类
        object Object {           def main(args: Array[String]): Unit = {
            var p1 = new Person();
          }
        }
    2.7:让trait继承类:
        在Scala中,trait也可以继承自class,此时这个class就会成为所有继承该trait的类的父类;
        class MyUtil {           def printMessage(msg : String) = println("msg : " + msg);
        }    
        //定义一个trait实现class
        trait Logger extends MyUtil{           def log(msg : String) = printMessage("log :" + msg);
        }
        //定义一个class实现trait
        class Person(val name : String) extends Logger{           def hello(): Unit ={
            log("hi , i am : " + name);
            printMessage("hi , i am : " + name);
          }
        }
        //定义一个object来测试实现的类
        object Object {           def main(args: Array[String]): Unit = {
            val p = new Person("张三");
            p.hello()
          }
        }

待续......

Scala学习教程笔记二之函数式编程、Object对象、伴生对象、继承、Trait、的更多相关文章

  1. Scala学习教程笔记三之函数式编程、集合操作、模式匹配、类型参数、隐式转换、Actor、

    1:Scala和Java的对比: 1.1:Scala中的函数是Java中完全没有的概念.因为Java是完全面向对象的编程语言,没有任何面向过程编程语言的特性,因此Java中的一等公民是类和对象,而且只 ...

  2. 学好Spark/Kafka必须要掌握的Scala技术点(二)类、单例/伴生对象、继承和trait,模式匹配、样例类(case class)

    3. 类.对象.继承和trait 3.1 类 3.1.1 类的定义 Scala中,可以在类中定义类.以在函数中定义函数.可以在类中定义object:可以在函数中定义类,类成员的缺省访问级别是:publ ...

  3. Python学习笔记二:函数式编程

    1:Python中,内置函数名相当于一个变量,指向内置函数.所以可以通过函数名调用相应函数,也可以给函数名赋值,改变它的内容,如:可以把另一个函数变量赋值给它,那它就指向了所赋值的函数了. 2:高级函 ...

  4. Scala学习教程笔记一之基础语法,条件控制,循环控制,函数,数组,集合

    前言:Scala的安装教程:http://www.cnblogs.com/biehongli/p/8065679.html 1:Scala之基础语法学习笔记: :声明val变量:可以使用val来声明变 ...

  5. 第2节 Scala中面向对象编程:1、类的定义;2、类的构造器;3、object和伴生对象;4、apply和main方法

    6.    类.对象.继承.特质 Scala的类与Java.C++的类比起来更简洁,学完之后你会更爱Scala!!! 6.1.   类 6.1.1.    类的定义 package cn.itcast ...

  6. [学习笔记]JavaScript之函数式编程

    欢迎指导与讨论:) 前言 函数式编程能使我们的代码结构变得简洁,让代码更接近于自然语言,易于理解. 一.减少不必要的函数嵌套代码 (1)当存在函数嵌套时,若内层函数的参数与外层函数的参数一致时,可以这 ...

  7. Python学习札记(二十) 函数式编程1 介绍 高阶函数介绍

    参考: 函数式编程 高阶函数 Note A.函数式编程(Functional Programming)介绍 1.函数是Python内建支持的一种封装,我们通过一层一层的函数调用把复杂任务分解成简单的任 ...

  8. Scala学习笔记(二):object、伴生对象和基本类

    object object 是只有一个实例的类.它的定义与Java中的class类似,如: // 单例对象 object AppEntry { def main(args: Array[String] ...

  9. Scala:用于Java的轻量级函数式编程

    Scala为Java开发提供了轻量级的代码选项,但是学习过程可能会很艰难.了解有关Scala的知识以及是否值得采用. 基于Java的语言通常涉及冗长的语法和特定于领域的语言,用于测试,解析和数值计算过 ...

随机推荐

  1. 海马玩模拟器——搭建React Native环境

    Visual Studio Emulator for Android 模拟器国内这网络环境不太用,所以使用海马玩模拟器,给大家推荐一下! 下面开始配置环境: 1)下载1.8+JDK,配置JDK环境参考 ...

  2. 高手进阶,终极内存技术指南——完整/进阶版 II (转)【转】

    转自:https://blog.csdn.net/lightseed/article/details/4630170 SDRAM芯片的预充电与刷新操作 预充电 由于SDRAM的寻址具体独占性,所以在进 ...

  3. web@前端--html,css,javascript简介、第一个页面(常用标签简介)

    1.什么是标签#1.在HTML中规定标签使用英文的的尖括号即`<`和`>`包起来,如`<html>`.`<head>`.`<body>`都是标签,#2. ...

  4. tcpdump抓取mysql语句

    抓包工具tcpdump的使用,抓取具体的sql语句 [root@test7_chat_api_im ~]# tcpdump -s -l - |strings tcpdump: listening on ...

  5. 阿里服务器配置swap

    说明:阿里服务器安装系统之后,默认swap为0 .该篇是阿里服务器上配置swap 的过程记录: 1.进入目录 cd /var/ 2.获取要增加的SWAP文件块(这里以1GB为例,count = 102 ...

  6. ThinkPHP框架整合phpqrcode生成二维码DEMO

    ThinkPHP框架发展到今天功能已经变得是非常强大了,但是ThinkPHP框架中没有二维码相关的库,因此我们可以通过整合phpqrcode来完成生成二维码的功能.想使用phpqrcode首先就要把p ...

  7. python介绍、解释器、变量及其它

    python 一.python及编程语言介绍 编程语言发展:机器语言==>汇编语言==>高级语言 机器语言:由数字电路发展而来编程都是靠0101的二进制进行 汇编语言:汇编语言的实质和机器 ...

  8. Golang服务器热重启、热升级、热更新(safe and graceful hot-restart/reload http server)详解

    服务端代码经常需要升级,对于线上系统的升级常用的做法是,通过前端的负载均衡(如nginx)来保证升级时至少有一个服务可用,依次(灰度)升级. 而另一种更方便的方法是在应用上做热重启,直接更新源码.配置 ...

  9. Confluence 6 缓存性能优化

    Confluence 的运行状态与缓存状态有这密切的关系.针对 Confluence 的管理员来说,尤其是大型站点的 Confluence 管理员,设置好缓存尤其显得关键. 希望修改缓存的大小: 进入 ...

  10. 关于deepin linux15.6-15.9.1系统播放视频卡顿解决办法

    关于deepin linux15.6-15.9.1系统播放视频卡顿解决办法 chrome浏览器 关闭chrome硬件加速模式 设置>高级>使用硬件加速模式 注释:由于视频卡顿是因显卡驱动问 ...