WPS宏(JSA)教程——类的定义及其组成部分

createh53个月前 (02-01)技术教程27

类这个概念要说新鲜在JSA中也算新鲜,但它又早就存在于JSA中。我们已经接触过类了:之前我们在介绍简单对象的过程中,接触到的对象类型,这其实就是一个类,只不过到ES6.0,才引入了class的写法。

一、什么是类?

如何去理解类?

在一家公司入职时,hr会让入职人员填写员工入职信息表填完信息表之后才算是公司的员工了;财务人员在做账时根据实际的报销单据收款单据银行回单等等原始凭证来填写的记账凭证;我们去银行办卡开户时,银行让我们填写的相关单子,以及办完之后交给我们的银行卡片

以上种种表单、单据、凭证、卡片,它们在当时的场景下都是一样的,无论谁来了填写的都是同一张表单模板(入职表,谁来入职都是填一样的表;记账凭证,任何会计填写做账,它的格式始终一样;银行卡片,所有人的银行卡都是一样的大小、同类型的卡片连外观都一样)。

这种将一类业务、同类事物抽像成一个模板,以后再使用这个模板在具体事务中形成一张张具体的单据。

在JSA以及编程语言中,我们就称这个模板为类;在具体事务中,填写完成之后的一张张表、拿到的一张张银行卡等等具体行为,在编程语言中,我们称这种形为为对象实例化

什么是类?

简单来说类是用于创建对象的模板。

在这个模板中,程序员们将其要实现的功能,通过程序代码,封装在类中。

我们在对象那一章节中接触到的类:

Bash
//定义一个远古动物的原型对象类型
function AcientAnimal()
{
  this.legsNumber = 4;
  this.hasTail = true;
  this.life = 40;
  this.language = 'No Language';
}
//三个原型对象原型链上的三个方法
AcientAnimal.prototype.speak = function(words)
{
  console.log(`No Language,No sence expressed by ${words}.`); 
}
AcientAnimal.prototype.hunt = function(food)
{
  console.log(`When hangury,knows to hunt ${food} for eating.`);
}
AcientAnimal.prototype.run = function(dis)
{
  console.log(`can run very fast by speed in ${dis}`);
}

上面这个其实也是一个类,因为JSA的类是建立在原型之上的。

二、声明类

我们如何声明(定义)一个类呢?

这里需要用到关键字class。

定义类的方式像前我们定义函数那样,有两种形式:

第一种:表达式形式

Bash
//1、匿名类表达式形式
let Circle = class{
    constructor(radius,center) {
    this.radius = radius;
    this.center = center;
  }
}
//上面我们定义了一个匿名类,并将之赋值给一个变量Circle,

//2、具名类表达式
let Circle = class ShapeCircle{
    constructor(radius,center) {
      this.radius = radius;
      this.center = center;
  }
}
//上面我们定义了一个具名类ShapeCircle,并将之赋值给变量Circle。

第二种:声明形式

Bash
class ShapeCircle{
    constructor(radius,center) {
      this.radius = radius;
      this.center = center;
  }
}

语法:

由上面的两种形式,我们不难看出,定义一个类的基本语法如下:

Bash
//1、声明形式
class className{
  constructor(参数1,参数2,....)
  {
    语句...
  }
  其他语名。
}

//2、表达式形式
变量名称 = class [calssName]{
  constructor(参数1,参数2,....)
  {
    语句...
  }
  其他语名。
}

类主体:

由上面的定义语法,我们可以看出,类的主体内容就是写在{}中间的代码了。我们可以在{}中间定义类的属性、方法、构造函数等等。

类的主体成员有如下:私有属性、公有属性、静态属性、构造函数、getter和setter。

三、主体组成部分

1、构造函数和extends:

constructor方法,是用于创建和初始化一个由类创建的对象的特殊方法。一个类只能拥有一个名为“constructor”的特殊方法,可以使用 super 关键字来调用父类的构造函数。我们在实例化一个类的时候,通常都new + 类名。通过这个new操作符,就是调用构造函数方法了。

extends:用于类声明或者类表达式中,以创建一个指定类的子类。

Bash
//定义一个动物类,这个类目前就三个属性:性别,生日,名字
class Animal{
  constructor(gendar,birthDay,name){
    this.gendar = gendar;
    this.birthDay = birthDay;
    this.name = name;
  }
}
//狗类,派生类自动物类,通过super来调用其父类中的构造函数
class Dog extends Animal{
  constructor(gendar,birthDay,name){
    super(gendar,birthDay,name);
  }
}
//猫类,派生类自动物类,通过super来调用其父类中的构造函数
class Cat extends Animal{
  constructor(gendar,birthDay,name){
    super(gendar,birthDay,name);
  }
}
//上面两个狗和猫的类就是由动物类派生出来的,能继承动物类的所有方法和属性。

//当我们要实例化一只狗的时候:
WangCai = new Dog('male','2023-7-2','旺财');
//我们再实例化一只猫
Garfield = new Cat('male','1977-7-2','加菲猫');

console.log(Garfield.name);//加菲猫
console.log(WangCai.name);//旺财

2、私有属性

属性在类当中包含两个方面的内容:字段和方法。

私有属性:就是只能在定义该属性的类中使用,类外部的其他任何地方都无法被访问到的属性。通常是与公有属性相对应的。

私有属性通过在属性前加上“#”(读作“hash”)前缀来创建。

Bash
class Human{
  #age;
  constructor(birth,name){
    //定义两个变量,用来存放当前日期和出生日期的日期对象
    let today = new Date(Date.now());
    let birthday = new Date(Date.parse(birth));
    
    this.birth = birth;
    this.name = name;
    //将两个日期的年份之差作为年龄
    this.#age = today.getFullYear()- birthday.getFullYear();
  }
  //定义一个获取人物年龄的方法。
  GetAge(){
    return this.#age;//返回年龄,向外部展示。
  }
}

LeeLei = new Human('April 25 2006',"李雷");
console.log(LeeLei.GetAge());//返回18
console.log(LeeLei.#age);//Error: Private field '#age' must be declared in an enclosing class

上面示例中#age就是一个私有字段,它是无法在实例外部访问的。

3、公有属性

同样的公有属性也是包含有公有字段和公有方法,公有方法也就是我们在简单对象中所讲的定义对象的方法。因此本小节主要讲述如何在类中定义公有类字段。

公有类字段:即是在类中声明的,我们可以访问、编辑、可枚举、可配置的属性。公有字段参与原型的继承。

声明一个公有类字段语法也很简洁。只需要在类的顶部写出你想要作为类的字段的名称就可以了。

Bash
class Car{
  owner;//以下声明了两个公有类字段,只不过该字段没有初始值;
  price;
  #lightType;//声明了一个私有类字段,也没有初始值;
  constructor(owner,price){
    this.owner = owner;//在属性初始化器中初始化公有字段
    this.price = price;
  }
}

let Car1 = new Car('李明',129800);
console.log(Car1.owner)//李明
console.log(Car1.price)//129800

在属性初始化器中只能引用constructor上面的字段,而无法引用其下面的字段。

4、静态属性

静态属性:是一组在属于类本身的属性,而不属于该类的实例的属性。静态属性的调用,与之前所说的公有属性的调用是不同的。

声明静态属性的语法格式是:static 变量名称,请看如下示例。

Bash
class someclass{
  static staticprop;
  constructor(){
    this.staticprop = '看看这里会不会被运行';//不会被运行
  }
  static getStaticProp(){
    return this.staticprop
  }
}

console.log(someclass.getStaticProp());//undefined,为什么会是这个值呢?

在上述示例中:我在属性初始化器中初始化了这个类的静态属性staticprop,并且希望通过静态方法能返回这个静态值。

但是,由于静态属性是属于类本身,而不属性于该类的具体实例,所以在这其中constructor这个构造函数是不会被运行的,因此这其中的赋值行为也就不会发生。所以最终返回的是undefined.

如何想要让静态属性能有所返回?需要类中声明一个叫做静态初始化块的特殊结构。

5、静态初始化块

静态初始化块是一个在类第一次加载时运行的代码块,在这其中是可以访问静态私有属性的。

静态初始化块的语法:以上方的示例为例:

Bash
class someclass{
  static staticprop;
  constructor(){
    someclass.staticprop = '看看这里会不会被运行';//不会被运行
  }
  static getStaticProp(){
    //return this.staticprop----下面的语句写成这样也是可以的。
    return someclass.staticprop
  }
  static{
    //this.staticprop----下面的语句写成这样也是可以的。
    someclass.staticprop = '孙悟空被迫到此一游!';
  }
}

console.log(someclass.getStaticProp());//孙悟空被迫到此一游!

由此可见,在一个类中,静态属性如果要被初始化,则必须要放置在静态初始化块中。

6、getter和setter

有时候通过简单方法对属性进行访问会出现各种不便,那么这个时候getter和setter就起到大作用了。

getter和setter的作用是:创建一个类似于对象属性的东西,但却不是属性,getter和setter其实是两个分别以get和set为前缀的方法,它就使得我们可以像操作对象属性那样操作它们。

如果一个字段只有getter而没有setter则表示这个字段是只读的;相反只有setter没有getter表示只写。

Bash
class Student{
  #name;
  constructor(name){
    this.#name = name;
  }
  get name(){
    return this.#name;
  }
  set name(value)
  {
    if(value!==this.#name) this.#name = value;
  }
}

HanMeimei = new Student();
HanMeimei.name = '韩美美';
console.log(HanMeimei.name);//韩美美

上述示例中的get和set就是相当于给类设置了一个叫name的属性,我们可以像操作属性那样操作这个方法。

好了,以上就是关于雷的相关内容。

关注我,持续共同学习,一起踏上wps宏(JSA)的登山之路。

#头条创作挑战赛#

相关文章

你知道子类引用为什么不能指向父类对象吗?反汇编一起看看

在java、C++等面向对象的语言中,实现多态的方式就是使用父类引用指向子类对象,所以父类引用指向子类对象是没有任何问题的,但是,大家有没有想过,子类引用可以指向父类对象吗?答案是不可以!但是为什么呢...

Java:Java中的多重继承问题(java中实现多重继承的方式)

  继承是面向对象编程 (OOP) 语言(如 Java)的主要功能之一。它是一种以增强软件设计中类重用能力的方式组织类的基本技术。多重继承是众多继承类型中的一种,是继承机制的一个重要原则。本文探讨了一...

父类实现了Serializable,子类不需要实现Serializable

相关注意事项 a)序列化时,只对对象的状态进行保存,而不管对象的方法; b)当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口; c)当一个对象的实例变量引用其他对象...

自学Java6(保姆级教学)——基本数据类型的转换

在上一期的文章中,我们认识了Java的几种运算符,先来简单回顾一下Java共有几类运算符:1.算数运算符:+,-,*,/(加减乘除),加上一个%(取余)2.赋值运算符:=3.关系运算符:˃,˂,==,...

产品设计阶段:To B软件产品设计流程总结

到了产品设计阶段,大部分产品经理(尤其是技术转型的产品经理)终于可以大大的喘一口气了,这个阶段的工作应该是产品人最最熟悉的环节了。网上关于产品设计(我总觉得这个叫需求分析)的方法论还真是多的很,场景分...

125题面试经常问的Java基础面试题整理与答案

1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。抽象包括两个方面,一是过程抽象,二...