zoukankan      html  css  js  c++  java
  • Scala面向对象编程与类型系统

    Scala支持面向对象编程, 其面向对象特性与Java有共同之处并添加了很多新的特性。

    类定义

    scala使用class关键字定义类:

    class MyComplex(real0:Double, image0:Double) {
    	var real:Double = real0;
    	var image:Double = image0;
    	private val eps:Double = 0.001;
    
    	def show() {
    		println("%f+%fi".format(this.real, this.image));
    	}
    }
    
    scala> var c = new MyComplex(1,1);
    c: MyComplex = MyComplex@49c17ba4
    
    scala> c.show()
    1.000000+1.000000i
    

    定义的语法与Java类似,同样采用this关键字访问实例自身。并且采用和Java类似的三种访问修饰符:

    • private: 仅类自身的方法可以访问

    • protected: 仅类自身和派生类的方法可以访问

    • public: 所有方法都可以访问, 默认访问权限

    scala类定义语法与Java最大的不同在于,类声明中含有参数声明。scala的整个类声明体即为一个函数体,我们称其为类的主构造函数。

    在类实例化时类声明中所有代码都将被执行,属性和方法的声明语句将定义相应的类成员。也因为如此, 所有属性声明时必须给出默认值.

    给出MyComplex类声明的Java版本, 可以让我们直观的认识主构造函数:

    class MyComplex {
    
    	public Double real;
    
    	public Double image;
    
    	public MyComplex(Double real0, Double image0) {
    		this.real = real0;
    		this.image = image0;
    	}  
    
    	public void show() {
    		println("%f+%fi".format(this.real, this.image));
    	}
    }
    

    辅助构造函数

    scala支持重载方法, 重载构造函数需要使用this关键字重载, 它们被称为辅助构造函数:

    class MyComplex(real0:Double, image0:Double) {
    	var real:Double = real0;
    	var image:Double = image0;
    	val eps:Double = 0.001;
    	
    	def this(real0:Int, image0:Int) {
    		this(real0.toDouble, image0.toDouble);
    	}
    
    	def show() {
    		println("%f+%fi".format(this.real, this.image));
    	}
    }
    

    调用辅助构造函数时,必须先调用主构造函数或其它已经定义好的构造函数

    object

    class关键字定义的类可以多次初始化, 而object关键字定义的是一个单例类,声明完成后即可访问,不需要再进行实例化:

    object Config {
    	var username:String = "";
    	var password:String = "";
    	var mode:Int = 0;
    
    	def show() {
    		println("username:" + this.username);
    		println("password" + this.password);
    		println("mode" + this.mode); 
    	}
    }
    
    scala> Config.username
    res: String = ""
    
    scala> Config.show()
    username:
    password
    mode0
    

    伴生对象

    在面向对象的设计模式中静态属性和方法被认为是一种不好的实践, 应该采用单例模式代替.

    伴生对象与类同名, 类对象和伴生对象可以互相访问对方的private成员, 编译后出现在同一个.class文件中.

    class User {
      var username:String = "";
      var password:String = "";
      var mode:Int = 0;
      
      User.add();
      println(User.count);
    }
    
    object User {
    	private var count:Int = 0;
    	
    	private def add() {
          this.count += 1;
    	}
    
    	def main(args: Array[String]) {
    		var u = new User();
    		println(this.count);
    	}
    }
    

    编译执行:

    $ scalac companion.scala
    cat: /release: No such file or directory
    
    $ ls
    User$.class       User.class        companion.scala
    
    $ scala User
    cat: /release: No such file or directory
    1
    1
    

    继承

    scala同样采用extends关键字进行继承:

    class MyComplex(real0:Double, image0:Double) {
    	var real:Double = real0;
    	var image:Double = image0;
    	val eps:Double = 0.001;
    
    	def this(real0:Int, image0:Int) {
    		this(real0.toDouble, image0.toDouble);
    	}
    
    	def show() {
    		println("%f+%fi".format(this.real, this.image));
    	}
    }
    
    class MyComplex2(real0:Double, image0:Double) 
    	extends MyComplex(real0, image0) {
    
    	override val eps:Double = 0.001;
    
    	override def show() {
    		if (this.real != 0) {
    			println("%f+%fi".format(this.real, this.image));			
    		}
    		else {
    			println("%fi".format(this.image));	
    		}
    	}
    }
    

    在继承声明中需要向基类构造函数传递实参.

    覆盖基类的非抽象属性和非抽象方法时必须使用override关键字.

    抽象类

    使用abstract关键字可以定义抽象类:

    abstract class AbstractComplex {
    	var real:Double;
    	var image:Double;
    	val eps:Double = 0.001;
    
    	def show;
    }
    

    抽象类允许不初始化属性或不实现方法,派生类在重写抽象属性和方法时不需要override关键字:

    class MyComplex(real0:Double, image0:Double) extends AbstractComplex {
    	var real:Double = real0;
    	var image:Double = image0;
    
    	def show() {
    		println("%f+%fi".format(this.real, this.image));
    	}
    }
    

    继承了抽象类的类必须实现所有属性和方法, 否则需要使用abstract关键字声明派生类仍然是抽象类:

    abstract class MyComplex(real0:Double, image0:Double) extends AbstractComplex {
    	var real:Double = real0;
    	var image:Double = image0;
    
    }
    

    trait

    trait类似于Java中的interface, 用于定义类的接口. 与Java类似, scala只允许继承一个实体或抽象类但允许实现多个trait.

    不同的是trait可以定义属性和方法, 并根据已有属性和方法生成新的属性和方法.

    trait ComplexTrait {
    	def equalWith(x:ComplexTrait): Boolean;
    	def notEqualWith()(x:ComplexTrait): Boolean = !equalWith(x);
    }
    

    scala使用extends关键字来继承trait, 若已经使用了extends则需使用with关键字对trait进行多继承:

    // class MyComplex(real0:Double, image0:Double) 
    //     extends ComplexTrait {...}
    class MyComplex(real0:Double, image0:Double) 
    	extends AbstractComplex with ComplexTrait {
    	var real:Double = real0;
    	var image:Double = image0;
    
    	def equalWith(x:ComplexTrait):Boolean = {
    		if (this.real == x.real && this.image == x.image) {
    			return true;
    		}
    		else {
    			return false;
    		}
    	}
    
    	def show() {
    		println("%f+%fi".format(this.real, this.image));
    	}
    }
    

    继承trait的类必须实现trait所有未实现的属性和方法.

  • 相关阅读:
    C#获取MAC地址
    C#洗牌
    删除前提示
    简单MD5加密
    读取EXCEL所有列名C#
    gridview二次加载样式丢失
    迅雷API接口(及示例演示)
    [转]Servlet过滤器介绍之原理分析
    [转]MySQL运行状态show status中文详解
    [转]如何修改mysql root密码
  • 原文地址:https://www.cnblogs.com/Finley/p/6386290.html
Copyright © 2011-2022 走看看