温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Scala2.11.7学习笔记(六)类和对象

发布时间:2020-07-15 20:39:26 来源:网络 阅读:559 作者:luchunli1985 栏目:大数据

鲁春利的工作笔记好记性不如烂笔头



1、扩展类    

    extends是Scala中实现继承的保留字;

class week extends month{......}

    week类继承了month类所有非私有成员;

    week类是month类的子类,month类是week类的超类;

    子类能重写超类的成员(字段、方法);

class week(val num : Int) extends month(val num : Int) {......}

    单例对象同样能从类中继承,与类的继承语法相同:object day extends week {......}

重写

    Scala中使用override保留字进行方法、字段重写

class week extends month {     override def firstday () {......} }

    override保留字声明其后的字段或方法是对超类的重写,也可以写在类定义参数中。

class week (override val lastday : String) extends month(val lastday : String)

    重新定义的字段和方法不可重写(override),方法不同(参数类型或个数)不可重写。

scala> class month {      |     def secondary(m : String) {      |         println("secondary is " + m);      |     }      | } defined class month   scala>   scala> class week extends month {      |     override def secondary(m : String) {    // 重写该方法      |         println("secondary is " + m);      |     }      | } defined class week

2、重写规则

   重写def

    用val:利用val能重写超类没有参数的方法;

    用def:子类方法与超类成员重名;

    用var:同时重写getter、setter方法,只重写getter方法报错。

   重写val:

    用val:子类的一个私有字段与超类的字段重名,getter方法重写超类的getter方法

   重写var:

    用var:当超类的var是抽象的才能被重写,否则超类的var都会被继承。

// 新建文件month.scala,内容为: abstract class month {     val zero : Int;     val one = 25;         // 可在子类中用val重写     var two = 15;         // 不可在子类中用var重写,因为不是抽象的     var three : Int;     def firstday ;        // 可在子类中用val重写     def now ;             // 可在子类中用var重写     def now_ ;             def lastday(m : Char) = {}    // 可在子类中用def重写 } // 通过scalac命令编译该文件 D:\LuclAppServ\scala-SDK\source>scalac month.scala D:\LuclAppServ\scala-SDK\source>javap.exe -private month.class // 通过javap命令查看生成的文件 Compiled from "month.scala" public abstract class month {   // val变量且被初始化了   private final int one;   // var变量且被初始化了   private int two;   // val变量但为抽象的,直接生成了getter方法   public abstract int zero();   // 只有getter方法   public int one();   // 同时具有getter和setter方法(=被转义为$eq)   public int two();   public void two_$eq(int);   // var变量但为抽象的,直接生成了getter和setter方法   public abstract int three();   public abstract void three_$eq(int);   // 其他抽象的方法   public abstract void firstday();   public abstract void now();   public abstract void now_();   // 具有方法体,非抽象方法   public void lastday(char);   // 构造函数   public month(); }

    通过IDE工具生成的week.scala代码如下

/**  * @author lucl  */ class week extends month {   override val zero : Int = 10;   override var three : Int = 3;   override def firstday : Unit = {     println("method of  firstday.");   }   override def now : Unit = {     println("method of now.");   }   override def now_ : Unit = {     println("method of now_.");   }    } object week {   def main (args : Array[String]) {     var w = new week();     println(w.zero + "\t" + w.now);   } }

    查看生成的week子类代码

D:\LuclAppServ\workspaces\scala\scalaproj\bin>javap -private week.class Compiled from "week.scala" public class week extends month {   private final int zero;   private int three;      public int zero();      public int three();   public void three_$eq(int);      public void firstday();      public void now();   public void now_();      public week();      public static void main(java.lang.String[]); } D:\LuclAppServ\workspaces\scala\scalaproj\bin>javap -private week$.class Compiled from "week.scala" public final class week$ {   public static final week$ MODULE$;   public static {};   public void main(java.lang.String[]);   private week$(); }

说明:

    子类构造器运行在超类构造器之后,在超类的构造器调用的子类被重写后,返回值可能不正确。

/**  * @author lucl  */ class A {   val num = 31;   val days = new Array[Int](num);   println("When invoke Class A the length of days is " + days.length + ".");   def dayLength = {     println("Class A : the length of days is " + days.length + ".")   } } /**  * @author lucl  */ object B extends A {   override val num = 7;      def main (args : Array[String]) {     dayLength;     println("The finally value of num is " + num);   } }

    运行结果:

Scala2.11.7学习笔记(六)类和对象

    构造B对象前先执行A的构造器,num被初始化为31,days被初始化为Array数组;

    Array数组初始化时需要调用num,但num被子类重写了,但此时B的构造器还未被调用,num被初始化为0,days被初始化为长度为0的数组;

    A的构造器执行完毕,执行B的构造器,num被初始化为7,但此时A中days已初始化过不会再更新其初始化信息,days的数组长度为0。

    解决方法:

        将超类的val声明为final(不可再被子类重写);

        将超类的val声明为lazy;

        在子类中使用提前定义语法。

    a. final

        当A类中的num声明为final val num : Int = 7,则子类中不可再重写该字段;

    b. lazy

/**  * @author lucl  */ class A {   lazy val num = 31;   // 通过lazy标注   val days = new Array[Int](num);   println("When invoke Class A the length of days is " + days.length + ".");   def dayLength = {     println("Class A : the length of days is " + days.length + ".")   } } /**  * @author lucl  */ object B extends A {   override lazy val num = 7;      def main (args : Array[String]) {     dayLength;     println("The finally value of num is " + num);   } }

    运行结果

Scala2.11.7学习笔记(六)类和对象   

    c. 提前定义

    把需要提前定义的语句块放在extends与超类之间,并后接with保留字。
    class B extends {override val num = 7; } with A {......}

/**  * @author lucl  */ object B extends {override val num = 7; } with A {   def main (args : Array[String]) {     dayLength;     println("The finally value of num is " + num);   } }

    执行结果:

Scala2.11.7学习笔记(六)类和对象

    

3、抽象类

    不能被实例的类叫做抽象类,用保留字abstract标记;

    抽象类的某个或某几个成员没有被完整定义,这些没有被完整定义的成员为抽象字段或方法。

/**  * @author lucl  */ abstract class year {   val name : Array[String];  // 抽象的val,带有一个抽象的getter方法   var num : Int;             // 抽象的var,带有抽象的getter/setter方法   def sign;                  // 没有方法体/函数体,是一个抽象方法 }

    只要类中有任意一个抽象成员,必须使用abstract标记;

    重写抽象方法、抽象字段不需要使用override保留字。

保护

    当一个类不希望被集成、拓展时,可在类声明前加上final保留字

final class year {......}

    当一个类的某些成员不希望被重写时,可在成员声明前加上final保留字

class year {final def sign {......}}


    当超类中的某些成员需要被子类继承,又不想对子类以外成员可见时,在成员声明前加上protected保留字;

    protected[this],将访问限定于当前对象(子类也不可访问),类似于private[this];

/**  * @author lucl  * 只要类中有一个成员是抽象的,则类就需要声明为抽象类  */ abstract class Human {   var name : String;      // 抽象字段   def sleep() : String;   // 抽象方法   def info (address : String); } /**  *   */ abstract class Teacher (tname : String, age : Int) extends Human {   println(tname + "\t" + age);      override var name : String = tname;      // 若将类声明为def sleep = "8 hours",在下面调用super.sleep()的位置会提示返回的为Unit   override def sleep() : String = "8 hours.";      def info (address : String); } /**  * Worker继承Teacher时有两个参数name和age需要从Worker中传递参数  * Worker的的参数名字需要与Teacher中一致,否则IDE会提示错误  */ class Worker(tname : String, age : Int, salary : Int) extends Teacher (tname, age) {   override def info (address : String) {     println(tname + "' home is in " + address);     println(tname + "'s age is " + age + ", earn ¥" + salary + ".");   }      override def toString = {     tname + " is a worker, sleep " + super.sleep;   } } object AbstractClassOps {   def main(args : Array[String]) {     val w = new Worker ("zhangsan", 25, 3000);     w.info("BeiJing");     println(w);   } } /**   zhangsan  25   zhangsan' home is in BeiJing   zhangsan's age is 25, earn ¥3000.   zhangsan is a worker, sleep 8 hours. */


4、类的private属性

/**  * @author lucl  */ // 默认是public类型的 class Person {   // age必须赋值,否则该类必须为abstract的   private var age : Int = 0;        // 没有private修饰默认是public的   // 无参的方法可以省略(),调用时可以省略();   def increment() = age += 1;   // 若声明的方法不带(),则调用时不可带()   def current = age;      // 类可以直接访问伴生对象的私有属性   def speak = Person.sayHello; } class Student {   /**    * 声明为private类型的参数,只能通过当前类的函数来访问    */   private var privateAge : Int = 0;   // 仅限于类的当前实例对象访问,其他传入的对象(如下面的other)将不可访问private[this]修饰的变量   private [this] val name : String = "";      // 自定义的getter/setter方法 ,用来操作私有字段    def age = privateAge;      def age_ (newAge : Int) {     privateAge = newAge;   }      /**    * this对象的使用,表示调用该方法的当前对象    */   def sameStudent (other : Student) = {       // 上面的等号表示有返回结果,否则最后的true会提示:     // a pure expression does nothing in statement position;      // you may be omitting necessary parentheses     if (this.privateAge != other.privateAge) {       false;     }     /**      *  此时通过other将无法访问该name对象      *  value name is not a member of Student      */     /*if (this.name != other.name) {       false;     }*/     true;   }      // 在student中则不可通过Person类直接访问sayHello方法,提示:   // method sayHello in object Person cannot be accessed in object Person   // def speak = Person.sayHello;   // 但可以通过如下方式访问:   var p = new Person;   p.speak;  // 这里会直接执行 } /**  * 对象为类的伴生对象,类为对象的伴生类  */ object Person {   def main (args : Array[String]) {     var p = new Person();     println("age is : " + p.age);    // 可以访问到私有属性     p.increment;     println("age is : " + p.age);     println("current is : " + p.current);          // 带有()则提示“Int does not take parameters”     // p.current();          val s = new Student();     // variable privateAge in class Student cannot be accessed in Student     // s.privateAge;     println(s.age);     s.age_(20);     println(s.age);   }   private def sayHello () {     println("Singleton object Person to say.");   } } /**  // 输出结果   age is : 0   age is : 1   current is : 1   Singleton object Person to say.   0   20 */


5、嵌套类

    Scala允许任何语法结构中嵌套任何语法结构,因此能在类中定义类,类似于Java中的内部类。

    内部类中可以访问外部类的成员,利用外部类.this或指针实现。

scala> class HelloWorld {pointto =>     val value2 = "HelloWorld";     class HI {         var value3 = HelloWorld.this.value2;         var value4 = pointto.value2;     } }  scala> var one = new HelloWorld; one: HelloWorld = HelloWorld@4b134f33 scala> one.value2; res52: String = HelloWorld scala> class Family (val hname : String, val wname : String) {     class Husband (var name : String) {         println("Husband is : " + name);     }          class Wife (var name : String) {         println("Wife is " + name);     }          def info () {         var husband = new Husband(hname);         var wife = new Wife(wname);         println("This family holds husband " + husband.name + ", wife " + wife.name);     } } scala> val f = new Family("Tom", "Jerry"); f: Family = Family@62de96e8 scala> f.info(); Husband is : Tom Wife is Jerry This family holds husband Tom, wife Jerry


Java内部类:内部类是属于外部类的;

/**  *   * @author lucl  * Java内部类示例  * 说明:Java内部类是从属于外部类的  */ public class JavaOuter {     private String name;     public JavaOuter (String name) {         this.name = name;     }     /**      * 内部类      */     // 一旦用static修饰内部类,它就变成静态内部类了。     class Inner {         private String name;         public Inner (String name) {             this.name = name;         }         public void foo (Inner inner) {             System.out.println("\t" + JavaOuter.this.name + "\t" + inner.name);         }     }          public void foo () {         System.out.println("Outer : " + this.name);     }     /**      * @param args      */     public static void main(String[] args) {         JavaOuter outer1 = new JavaOuter("Spark");         JavaOuter outer2 = new JavaOuter("Hadoop");                  JavaOuter.Inner inner1 = outer1.new Inner("scala");         JavaOuter.Inner inner2 = outer2.new Inner("java");                  outer1.foo();         inner1.foo(inner1);         outer2.foo();         inner2.foo(inner2);                  outer1.foo();         inner1.foo(inner2);    // 在这里inner1可以调用inner2     } } /**      // 输出结果     Outer : Spark             Spark    scala     Outer : Hadoop             Hadoop    java     Outer : Spark             Spark    java */

Scala内部类:内部类是属于外部类的对象的;

/**  * @author lucl  * Scala内部类示例  * 说明:Scala内部类是从属于外部类的对象的  */ class ScalaOuter(val name : String) {outer =>   /**    * 内部类    */   class Inner (val name : String) {     def foo (inner : Inner) {       println("\t" + outer.name + "\t" + inner.name + ".");     }   }      def foo () {     println("Outer : " + outer.name);   } } object OOPInScala {     /**    * main方法    */   def main (args : Array[String]) {     val outer1 = new ScalaOuter ("Spark");     val outer2 = new ScalaOuter ("Hadoop");         val inner1 = new outer1.Inner("scala");     val inner2 = new outer2.Inner("java");     outer1.foo;     inner1.foo(inner1);          outer2.foo;     inner2.foo(inner2);          // 对于scala来说,这inner1调用foo方法传递参数时,是不可以将inner2作为参数传递的     // IDE提示:type mismatch; found : outer2.Inner required: outer1.Inner     // inner1.foo(inner2);   } } /**     // 输出结果     Outer : Spark           Spark scala.     Outer : Hadoop           Hadoop  java. */


向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI