ASP.NET AJAX(6)__Microsoft AJAX Library中的面向对象类型系统命名空间类类——构造函数类——定义方法类——定义属性类——注册类类——抽象类类——继承类——调用父类方

如果我们可以合理的使用面向对象编程,我们可以提高代码的复用性和可维护性,这里强调的是合理的使用,有了面向对象类型系统,就可以使用一些成熟的设计方式

命名空间

  • 合理的组织大量的类型,使开发人员能够方便的找到他们所需要的类型
  • 可重复注册命名空间,每个独立的脚本模块前都要注册命名空间以保证命名空间存在

  • 定义构造函数
  • 定义成员(方法、属性、事件)
  • 注册类

类——构造函数

  • 类的构造函数即为function定义
  • 通常用于初始化域变量
  • 自由成员使用下划线开头(形式上的封装)

类——定义方法

  • 使用prototype定义
  • MyNamespace.MyClass.prototype={method1:function{},method2:function()}

类——定义属性

  • Microsoft AJAX Library的面向对象类型系统将get_xxx和set_xxx开头的方法认做属性(一种约定)
  • 避免定义只写属性,使用某个方法替代

类——注册类

  1. Tye.registerNamespace("MyNamespace");
  2. MyNamespace.MyClass=function(parm1,…){…}
  3. MyNamespace.MyClass.prototype={…}
  4. MyNamespace.MyClass.registerClass("MyNamespace.MyClass");
一个定义以及使用类的示例

创建一个js文件

我们可以在js文件一开始,写上/// <reference name="MicrosoftAjax.js" />这样一段代码,就可以在VS里得到很多关于Microsoft AJAX Library的代码提示

/// <reference name="MicrosoftAjax.js" />

Type.registerNamespace("MyNamespace");//注册一个命名空间
MyNamespace.Employee = function(name) {//定义一个构造函数
    this._name = name ? name : "Anonymous";//初始化域变量
    this._year = 0; //初始化域变量
}

MyNamespace.Employee.prototype =//定义类成员
{
    get_name: function() {//定义属性
        return this._name;
    },//注意都是用逗号分割的
    get_year: function() {//定义属性
        return this._year;
    },
    set_year: function(value) {//定义属性
        this._year = value;
    },

    calculateSalary: function() {//定义一个方法
        return this._year * 1000;
       // throw Error.notImplemented();
    },

    getDescription: function() {//定义一个方法
        return String.format("{0} gets {1} yuan per month", this._name, this.calculateSalary());
    }
}
MyNamespace.Employee.registerClass("MyNamespace.Employee"); //注册类

这样,我们就定义了一个简单的Employee类

创建一个aspx页面,并使用我们定义好的Employee类

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ScriptManager ID="s" runat="server">
            <Scripts>
                <asp:ScriptReference Path="~/Demo05/Employee.js" />
            </Scripts>
        </asp:ScriptManager>
        <div id="info">
        </div>

        <script language="javascript" type="text/javascript">
               function display(text) {
                   document.getElementById("info").innerHTML+=text+"<br/>";
               }

               var xiaoyaojian = new MyNamespace.Employee("xiaoyaojian");
               xiaoyaojian.set_year(4);
               display(xiaoyaojian.getDescription());
        </script>
    </form>   
</body>
</html>

调试,出结果,用法很简单,和c#类相同

类——抽象类

  • 包含抽象方法的类即为抽象类
  • MyNamespace.MyClass.prototype{this._mymethod=function{throw Error.notImplemented();}}//包含抽象方法

类——继承

  • 调用父类的构造函数
  • 有父类的类必须调用父类的构造函数,否则会丢失继承效果(不和c#相同,c#自动调用)
  • MyNamespace.MyClass=function(){MyNamespace.MyClass.initializeBase(this,[param1,…])}
  • 注册时候提供父类
  • 可以直接以普通方式实现父类的抽象成员
  • toString方法无法被继承

类——调用父类方法

  • MyNamespace.MyClass.prototype={myMethod:function(param1,…){MyNamesapce.MyClass.callBaseMethod(this,"meMethod",[param1,…])}}
一个示例

修改上面的Employee.js

/// <reference name="MicrosoftAjax.js" />

Type.registerNamespace("MyNamespace");//注册一个命名空间

MyNamespace.Employee = function(name) {//定义一个构造函数
    this._name = name ? name : "Anonymous";//初始化域变量
    this._year = 0; //初始化域变量
}

MyNamespace.Employee.prototype =//定义类成员
{
    get_name: function() {//定义属性
        return this._name;
    },//注意都是用逗号分割的
    get_year: function() {//定义属性
        return this._year;
    },
    set_year: function(value) {//定义属性
        this._year = value;
    },

    calculateSalary: function() {//定义一个方法
        //return this._year * 1000;
        throw Error.notImplemented();//抛出异常,这个方法是抽象方法,说明这个类是抽象类
    },

    getDescription: function() {//定义一个方法
        return String.format("{0} gets {1} yuan per month", this._name, this.calculateSalary());
    }
}
MyNamespace.Employee.registerClass("MyNamespace.Employee"); //注册类
//MyNamespace.Employee.registerClass("MyNamespace.Employee", null, MyNamespace.IEmployee);//注册类


MyNamespace.Intern = function(name) {
    MyNamespace.Intern.initializeBase(this, [name]);//调用父类构造函数
}

MyNamespace.Intern.prototype =
{
    calculateSalary: function() {
        return 2000;

    },
    getDescription: function() {
        var description = MyNamespace.Intern.callBaseMethod(this, "getDescription");//调用父类方法
        return description + ",What a poor intern!";

    }
}

MyNamespace.Intern.registerClass("MyNamespace.Intern", MyNamespace.Employee); //注册这个类,继承MyNamespace.Employee


MyNamespace.Vendor = function(name) {
    MyNamespace.Vendor.initializeBase(this, [name]);
}

MyNamespace.Vendor.prototype =
{
    calculateSalary: function() {
        //return 2000;
        return 5000 + 1000 * (this.get_year() - 1);
    }
}

MyNamespace.Vendor.registerClass("MyNamespace.Vendor", MyNamespace.Employee);


MyNamespace.FulltimeEmployee = function(name) {
    MyNamespace.FulltimeEmployee.initializeBase(this, [name]);
}

MyNamespace.FulltimeEmployee.prototype =
{
    calculateSalary: function() {
        //return 2000;
        return 15000 + 2000 * (this.get_year());
    }
}

MyNamespace.FulltimeEmployee.registerClass("MyNamespace.FulltimeEmployee", MyNamespace.Employee);

这时,我们再打开刚才的页面,就会出现一个方法未实现错误,因为我们实例化一个抽象类,这不符合逻辑

修改页面代码

<script language="javascript" type="text/javascript">
               function display(text) {
                   document.getElementById("info").innerHTML+=text+"<br/>";
               }

               var xiaoyaojian = new MyNamespace.Intern("Xiaoyaojian");
               xiaoyaojian.set_year(3);
               display(xiaoyaojian.getDescription());

               var xiaobai = new MyNamespace.Vendor("Xiaobai");
               xiaobai.set_year(3);
               display(xiaobai.getDescription());

               var xiaobaigege = new MyNamespace.FulltimeEmployee("Xiaobaigege");
               xiaobaigege.set_year(5);
               display(xiaobaigege.getDescription());
        </script>

这样,成功的使用了我们创建了继承Employee的三个类

接口

  • 与类的定义方法大致相同
  • 构造函数抛出异常
  • 所有的方法抛出异常(只有方法签名,不提供实现)
  • 注册接口时使用registerInterface方法
  • 接口无法继承其他接口

接口定义

  • MyNamespace.IMyInterface=function(){throw Error.notImplemented()}
  • MyNamespace.IMyInterface.prototype={myMethod:function(){throw Error.notImplemented()}}
  • MyNamespace.IMyInterface.registerInterface(“MyNamespace.IMyInterface”);

接口实现

  • 在使用registerClass方法注册类时候可以传入额外的参数来实现接口
  • MyNamespace.MyClass.registerClass("MyNamespace.IMyInterface",null,IMyInterface1,IMyInterface1,…);
一个关于接口的示例

同样,还是修改Employee.js文件

/// <reference name="MicrosoftAjax.js" />

Type.registerNamespace("MyNamespace"); //注册一个命名空间

MyNamespace.IEmployee = function() {
    throw Error.notImplemented();
}
MyNamespace.IEmployee.prototype = {
    calcaulateSalary: function() {
        throw Error.notImplemented();
    }
}
MyNamespace.IEmployee.registerInterface("MyNamespace.IEmployee");


MyNamespace.Employee = function(name) {//定义一个构造函数
    this._name = name ? name : "Anonymous";//初始化域变量
    this._year = 0; //初始化域变量
}

MyNamespace.Employee.prototype =//定义类成员
{
    get_name: function() {//定义属性
        return this._name;
    },//注意都是用逗号分割的
    get_year: function() {//定义属性
        return this._year;
    },
    set_year: function(value) {//定义属性
        this._year = value;
    },

    calculateSalary: function() {//定义一个方法
        //return this._year * 1000;
        throw Error.notImplemented();//抛出异常,这个方法是抽象方法,说明这个类是抽象类
    },

    getDescription: function() {//定义一个方法
        return String.format("{0} gets {1} yuan per month", this._name, this.calculateSalary());
    }
}
//MyNamespace.Employee.registerClass("MyNamespace.Employee"); //注册类
MyNamespace.Employee.registerClass("MyNamespace.Employee", null, MyNamespace.IEmployee);//注册类


MyNamespace.Intern = function(name) {
    MyNamespace.Intern.initializeBase(this, [name]);//调用父类构造函数
}

MyNamespace.Intern.prototype =
{
    calculateSalary: function() {
        return 2000;

    },
    getDescription: function() {
        var description = MyNamespace.Intern.callBaseMethod(this, "getDescription");
        return description + ",What a poor intern!";

    }
}

MyNamespace.Intern.registerClass("MyNamespace.Intern", MyNamespace.Employee); //注册这个类,继承MyNamespace.Employee


MyNamespace.Vendor = function(name) {
    MyNamespace.Vendor.initializeBase(this, [name]);
}

MyNamespace.Vendor.prototype =
{
    calculateSalary: function() {
        //return 2000;
        return 5000 + 1000 * (this.get_year() - 1);
    }
}

MyNamespace.Vendor.registerClass("MyNamespace.Vendor", MyNamespace.Employee);


MyNamespace.FulltimeEmployee = function(name) {
    MyNamespace.FulltimeEmployee.initializeBase(this, [name]);
}

MyNamespace.FulltimeEmployee.prototype =
{
    calculateSalary: function() {
        //return 2000;
        return 15000 + 2000 * (this.get_year());
    }
}

MyNamespace.FulltimeEmployee.registerClass("MyNamespace.FulltimeEmployee", MyNamespace.Employee);

这时,在页面中还使用这些类还是没有问题的,如果我们要体现这个接口的继承,可以在页面<script>中添加如下代码

display("Xiaoyaojian implements 'IEmployee' interface:" + MyNamespace.IEmployee.isImplementedBy(xiaoyaojian))

za在页面中,我们可以看到返回的结果是true,说明Employee实现了接口IEmployee

枚举

  • 枚举即为Number
  • 增加可读性
  • 可以定义为标记
  • 每个枚举类型均有toString和parse方法

枚举的定义

MyNamespace.MyEnum=function(){throw Error.notImplemented();}
MyNamespace.MyEnum.prototoype={item1:1,item2:2,item3:4}
MyNamespace.MyEnum.registerEnum(“MyNamespace.MyEnum”,[true])//true表示是否定义一个标记
一个定义以及使用枚举的示例

修改Employee.js

/// <reference name="MicrosoftAjax.js" />

Type.registerNamespace("MyNamespace"); //注册一个命名空间

MyNamespace.EmployeeType = function() {
    throw Error.notImplemented();//抛出异常,无法实例化
}
MyNamespace.EmployeeType.prototype =//定义成员
{
    Intern: 0,
    Vendor: 1,
    FulltiomEmployee: 2
}
MyNamespace.EmployeeType.registerEnum("MyNamespace.EmployeeType");//注册枚举

MyNamespace.IEmployee = function() {
    throw Error.notImplemented();
}
MyNamespace.IEmployee.prototype = {
    calcaulateSalary: function() {
        throw Error.notImplemented();
    },
    get_type: function() {
        throw Error.notImplemented();
    }
}
MyNamespace.IEmployee.registerInterface("MyNamespace.IEmployee");


MyNamespace.Employee = function(name) {//定义一个构造函数
    this._name = name ? name : "Anonymous";//初始化域变量
    this._year = 0; //初始化域变量
}

MyNamespace.Employee.prototype =//定义类成员
{
    get_name: function() {//定义属性
        return this._name;
    },//注意都是用逗号分割的
    get_year: function() {//定义属性
        return this._year;
    },
    set_year: function(value) {//定义属性
        this._year = value;
    },

    calculateSalary: function() {//定义一个方法
        //return this._year * 1000;
        throw Error.notImplemented();//抛出异常,这个方法是抽象方法,说明这个类是抽象类
    },

    getDescription: function() {//定义一个方法
        return String.format("{0} gets {1} yuan per month", this._name, this.calculateSalary());
    }
}
//MyNamespace.Employee.registerClass("MyNamespace.Employee"); //注册类
MyNamespace.Employee.registerClass("MyNamespace.Employee", null, MyNamespace.IEmployee);//注册类


MyNamespace.Intern = function(name) {
    MyNamespace.Intern.initializeBase(this, [name]);//调用父类构造函数
}

MyNamespace.Intern.prototype =
{
    calculateSalary: function() {
        return 2000;

    },
    getDescription: function() {
        var description = MyNamespace.Intern.callBaseMethod(this, "getDescription");
        return description + ",What a poor intern!";

    },
    get_type: function() {
        return MyNamespace.EmployeeType.Intern;
    }
}

MyNamespace.Intern.registerClass("MyNamespace.Intern", MyNamespace.Employee); //注册这个类,继承MyNamespace.Employee


MyNamespace.Vendor = function(name) {
    MyNamespace.Vendor.initializeBase(this, [name]);
}

MyNamespace.Vendor.prototype =
{
    calculateSalary: function() {
        //return 2000;
        return 5000 + 1000 * (this.get_year() - 1);
    },
    get_type: function() {
        return MyNamespace.EmployeeType.Vendor;
    }
}

MyNamespace.Vendor.registerClass("MyNamespace.Vendor", MyNamespace.Employee);


MyNamespace.FulltimeEmployee = function(name) {
    MyNamespace.FulltimeEmployee.initializeBase(this, [name]);
}

MyNamespace.FulltimeEmployee.prototype =
{
    calculateSalary: function() {
        //return 2000;
        return 15000 + 2000 * (this.get_year());
    },
    get_type: function() {
        return MyNamespace.EmployeeType.FulltimeEmployee;
    }
}

MyNamespace.FulltimeEmployee.registerClass("MyNamespace.FulltimeEmployee", MyNamespace.Employee);

这时,在页面中<script>中添加如下代码

var type = MyNamespace.EmployeeType.toString(xiaoyaojian.get_type());
               display(String.format("{0} is a {1}", xiaoyaojian.get_name(), type));

刷新页面,出现效果,如果我们不使用MyNamespace.EmployeeType.toString(),这里就会出现一个“1”,符合我们的定义

定义个作为标记的枚举类

在Employee.js里添加如下内容

MyNamespace.MyFlags = function() {
    throw Error.notImplemented();
}
MyNamespace.MyFlags.prototype =
{
    Item1:1,
    Item2:2,
    Item3:4,
    None:0,
    All:7
}
MyNamespace.MyFlags.registerEnum("MyNamespace.MyFlags",true);

在页面中我们可以这样使用

var all = MyNamespace.MyFlags.All;
               display(all);
               display(MyNamespace.MyFlags.toString(all));

               display(MyNamespace.MyFlags.parse("Item1,Item3")); //"Item1,Item3"这是一个标准的表示方法,结果为Item1+Item3的结果

反射方法

  • Type.prototype.getBaseType//得到父类
  • Type.prototype.getInterfaces//得到实现的接口
  • Type.prototype.getName//得到类名
  • Type.prototype.implementsInterface//得到是否实现某接口
  • Type.prototype.inheritsFrom//确定一个类型是否从特定的基类型继承
  • Type.prototype.isImplementedBy//确定实例是否实现了特定接口
  • Type.getRootNamespaces//返回一个数组,包含对客户端应用程序的所有根命名空间的引用
  • Type.prototype.isInstanceOfType//如果当前 Type 在 object 表示的对象的继承层次结构中,或者如果当前 Type 是 object 支持的接口,则为 true
  • Type.isClass
  • Type.isInterface
  • Type.isNamespace
  • Type.isEnum
  • Type.isFlags
  • Type.parse

后面这几个,我就不多做解释啦

到此讲完

今天是小白的生日,纪念一下

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏开发与安全

算法:静态查找表(Static Search Table)(顺序查找、二分查找、插值查找、斐波纳契查找)

查找表(Search table)是由同一类型的数据元素(或记录)构成的集合。关键字(key)是数据元素中某个数据项的值,又称为键值,用它可以表示一个数据元素,...

2255
来自专栏desperate633

LeetCode Delete Node in a Linked ListQuestion题目分析代码

给定一个单链表中的一个等待被删除的节点(非表头或表尾)。请在在O(1)时间复杂度删除该链表节点。

723
来自专栏恰同学骚年

.NET基础拾遗(1)类型语法基础和内存管理基础

在.NET中所有的内建类型都继承自System.Object类型。在C#中,不需要显示地定义类型继承自System.Object,编译器将自动地自动地为类型添...

1012
来自专栏我杨某人的青春满是悔恨

深入理解 weak-strong dance

这时handler持有 Block 对象,而 Block 对象虽然捕获了weakSelf,延长了weakSelf这个局部变量的生命周期,但weakSelf是附有...

804
来自专栏华仔的技术笔记

再议Block

2897
来自专栏前端黑板报

Javascript即将迎来Optional Chaining

Optional Chaining 现在处于 Stage 1。 它是什么? Optional Chaining 使我们能检查一个对象上面是否存在某属性。其它一些...

3555
来自专栏一个会写诗的程序员的博客

《Kotin 编程思想·实战》

Xtend是Eclipse推出的一个新的JVM语言,并无意替代Java,而是以己之长补Java之短,精简代码,无类型,改进可读和维护。Eclipse Xtend...

1093
来自专栏IT笔记

2016头条校招笔试题(LRU)算法之JAVA实现

操作系统中可以使用LRU(Least Recently Used)内存淘汰旧数据的策略,如果内存需要加载新数据但空间不足,则会按照最近访问时间进行排序,并将最老...

32810
来自专栏后端之路

Dubbo异常处理

小伙伴在使用dubbo过程中推出了疑问,部分自定义异常不见了,变成了RuntimeException。并且message超长。 如下图 我们来查看一下Dubb...

5465
来自专栏一个会写诗的程序员的博客

Kotlin 中的集合类排序Kotlin 开发者社区

Kotlin使用扩展方法构建在Java Collection框架之上。这大大提高了可用性和可读性,而无需第三方依赖,如Apache Commons或Guava。

1265

扫码关注云+社区