仓颉:关于封装,继承,多态

       在对于仓颉有了初步了解之后,我们自然会想在我们之前所学习,编写的简单代码上添加一些其他的功能,今天我们就来讲几个重要的小功能

封装

        为了提高数据访问的安全性,我们可以使用访问修饰符private。那么我们应该通过什么方法提高呢,我们有两种方法:1.通过方法 2.通过属性设计器。

参考如下代码

package cjchapter4.chapter1

public class User {

    private var a1: Int64 = 0

    public func getA1(): Int64 {
        this.a1
    }

    public func setA1(a1: Int64): Unit {
        this.a1 = a1
    }

    public  mut  prop   propA1:Int64{

        get(){

            this.a1
        }
        set(a1)
        {
            if(a1>0)
            {
                 this.a1 =a1
            }
            else{

                println("传递的数据:${a1},不能够设置值")
            }
             
        }
    }
}

当然啦,在使用上述代码的时候,记得在main,cj里面把主体函数写好哦

继承

       很多同学在第一次学完仓颉,并尝试自己去蜀绣额属于自己的第一个代码的时候,通常都会遇到一个问题,就是在编写的过程中代码里面会出现好多好多的重复的变量,方法以及属性设计器。所以大多数同学的代码会看上去杂乱不堪。这个时候呢,我们就需要用到仓颉语言中的继承方法啦。

首先我们要了解仓颉的继承关键字是什么。仓颉的继承的关键字:<: 

那么继承的作用是什么呢?减少子类中冗余重复的变量和方法、属性设计器

特别要注意同名变量的继承问题,参照如下代码

package  cjchapter4.chapter2

(1)
public  open  class   Base{

    private var  a1 : Int64  =10

    public  func  getA1():Int64{

        this.a1
    }

}

public  class  Son <: Base{

(2)
      var  a1 : Int64  =100

}

public  func  exec1()
{
    var  son :Son  = Son()
    println("${son.a1}")

    var  base :Base  =Base()
    println("base.a1的值为:${base.getA1()}")

   
}

上述代码中有两处需要解释一下:

(1)仓颉中类要被继承,要显示的使用关键字open

(2)子类中不能够声明和父类同名的变量。加了private访问修饰符,所谓的同名变量是可以通过编译的,但是父类的同名变量,没有被子类继承

那么有同学会问,我们一个怎么书写减少子类重复的代码呢

我们可以看看下面的代码

package  cjchapter4.chapter3

public open class  Emp{

     var name : String  = ""

     var  age :Int16  = 0 

     public  func  showInfo()
     {
         println("群友的姓名是:${name},年龄是:${age}")
     }

}

public  class Manager <:Emp{


}

public class  Worker <:Emp{


}

public  func   exec2()
{
     var  m : Manager  = Manager()
     m.name = "蓝星悼"
     m.age  =20
     m.showInfo()

}

 同样的我们对以上代码做一些注释:

(1)private-default-protected-public   访问修饰符的大小

接下来我们要学习本次的重要内容,也就是多态。

多态

首先我们要了解多态的定义:同一个方法名,不同的实现的结果。

多态呢,有两个具体的体现:1.方法重载 2.方法重写

那么我们就先来讲讲方法重载:

       相同的方法名,不同的参数列表(参数的个数或参数的类型),与返回值类型无关,与static关键字无关。决定调用哪个重载的方法是由参数决定的,所以我们把方法重载也叫做编译时多态。

package  cjchapter4.chapter3

//private-default-protected-public   访问修饰符的大小
public open class  Emp{

     var name : String  = ""

     var  age :Int16  = 0 

     public  func  showInfo()
     {
         println("群友的姓名是:${name},年龄是:${age}")
     }
     public   func   eat():Unit
     {
         println("正常的聊天")
     }
     public   func  eat(name:String):String
     {
         println("聊天的内容可以自行定义:${name}")
         name
     }

}

public  class Manager <:Emp{





}

public class  Worker <:Emp{


}

public  func   exec2()
{
     var  m : Manager  = Manager()
     m.name = "蓝星悼"
     m.age  =20
     m.showInfo()

     m.chat("早早早")

}

如上代码就是对方法重载最好的体现。

接下来我们来看看方法重写:

        在继承关系中,子类和父类具有相同的方法名,相同的参数列表(参数的个数和类型),相同的返回值类型,与static无关。决定调用哪个重名的方法,是由创建的对象来决定的。

动态绑定机制,一个父类指向多个子类的现象,也就是大类型指向多个子类型的现象。

参考如下代码

package  cjchapter4.chapter3

public open class  Emp{

     var name : String  = ""

     var  age :Int16  = 0 

     public  func  showInfo()
     {
         println("群友的姓名是:${name},年龄是:${age}")
     }
     public   func   eat():Unit
     {
         println("正常的聊天")
     }
     public   func  eat(name:String):String
     {
         println("聊天的内容可以自行定义:${name}")
         name
     }

     public     open  func  run():Unit{

        println("父类base的run方法-正常跑")

        "111"

     }

}

public  class Manager <:Emp{


     public   override  func  run():Unit{
        println("子类Manager的run方法->慢慢跑")
     }



}

public class  Worker <:Emp{


}

public  func   exec2()
{
     var  m : Manager  = Manager()
     m.name = "蓝星悼"
     m.age  =20
     m.showInfo()
     m.chat("早早早")

     // 方法重写,调用哪个具体的方法,是由创建的对象来决定的
     var  m1 :Emp  =Manager()
     m1.run()

     var m2 :Emp   =Emp()
     m2.run()


}

 同样的上述代码中有两点需要注意的:
(1)private-default-protected-public   访问修饰符的大小

(2)在类中的方法,如果是不标注open关键字,子类是不能够重写的

抽象

具体的体现是抽象类和接口,为什么有抽象类和接口,其实一句话:就是为了加强多态,加强动态绑定,就是为了方法重写。

抽象类和接口,都不能实例化,都属于大类型,一定会有子类,怎么去实例化呢?通过子类完成实例化。 抽象类和接口绑定子类,抽象方法被子类重写,运行时多态。

抽象类被继承后,抽象类要声明成public,抽象类中可以有构造函数,抽象类中的构造函数要被子类依赖(显示的,隐私的)

抽象类被继承后,抽象类要声明成public

package  cjchapter4.chapter4

public  abstract  class  Base{

    //抽象类中可以有构造函数  主构造函数
    public Base(a1:Int64)
    {

    }

    public    func  open():Unit
}

public    class  Son <: Base{

    public Son()
    {
        super(10)
    }

    public  func  open():Unit{
        
    }


}
package cjchapter4.chapter4

public abstract class Base {

    //抽象类中可以有构造函数  主构造函数
    public Base(a1: Int64) {
    }

    public func open(): Unit
}

public class Son1 <: Base {
    public Son1() {
        super(10)
    }

    public func open(): Unit {
    }
}

public class Son2 <: Base {
    public Son2() {
        super(10)
    }

    public func open(): Unit {
    }
}

public func exec4() {
    // 抽象类不能被实例化
    //var base :Base  =Base(20)

    // 父类base对象绑定
    var base1: Base = Son1()
    var base2: Base = Son2()
    // 引用类型赋值
    base1 = base2
}

接口被继承,接口也必须声明成public,接口中不能有构造函数,不能去实例化,通过子类完成实例化

package  cjchapter4.chapter5

public interface   A{


}

public class  UserA <:A{


}

此外,有两点需要我们特别注意

   仓颉的方法的参数都是不可变变量

package  cjchapter4.chapter6

public class User{

    var  a1:Int64 = 0

    public init(a1:Int64) {

        //仓颉方法中参数是不可变量,不能修改其值
        //a1 =100
        //var  a2  =a1
        this.a1 = a1
    }
    public  func   changeA1()
    {
        //仓颉语言不支持前置的++运算,只支持后置++
         this.a1 ++ 
    }

    public  func   changeA1( u1:User)
    {
        var u2 :User  =User(200)
        //u1是一个不可变变量
        //u1 = u2
        //这样是可以的
        u2 = u1
        println("${u2.a1}")//101 

    }

}

public  func  exec6()
{
     var  u1 :User  =User(100)
     u1.changeA1()
     println("u1.a1的值为:${u1.a1}")//101

     u1.changeA1(u1)
}

接口和抽象类的属性设计器被重写时,不能够做任何的修改

package cjchapter4.chapter8

public open class Base {}

public class Son <: Base {}

public interface UserInterfaces {

    //接口中声明了抽象的属性设计器
    public mut prop propValue: Base
}

public class UserClass <: UserInterfaces {

    //var son  =Son()  // 这样是不可以的

    //接口中对属性设计器,不能做任何的继承的修改
    var son = Base()
    public mut prop propValue: Base {
        get() {
            son
        }
        set(value) {
            this.son = value
        }
    }
}
package cjchapter4.chapter9

public open class Base {}

public class Son <: Base {}

public abstract class ABUser {

    //接口中声明了抽象的属性设计器
    public mut prop propValue: Base

    public open func show(): Unit
}

public class User <: ABUser {
    var son = Base()
    public mut prop propValue: Base {
        get() {
            son
        }
        set(value) {
            this.son = value
        }
    }
    public override func show(): Unit {
    }
}

 但是方法重写可以杯修改,而他之所以可以被修改,是基于继承关系

package cjchapter4.chapter10

public  open  class  Base{

}

public class Son <:Base{

}

public  interface UserInterface{

    public  func  execFun():Base
}

public  class  User <:UserInterface{

     public  func  execFun():Base{

        Son()
     }
}

       至此我们学习了仓颉语言中的封装,继承,多态和抽象,要多加练习并要牢牢掌握,在今后的学习中我们可以给我们的这一个小小的简单的仓颉代码加上许许多多的新功能。相信经过学习,咱们一定能搞定仓颉语言。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值