鸿蒙ArkTS中的面向对象编程

时间:2024-11-01 12:47:44

ArkTS是TypeScriptS的超集,而TS又是JavaScript的超集,意味着有JavaScript编程基础、结合一些TypeScript的使用经验就可以很快上手ArkTS。

作为一门面向对象语言的学习,了解和掌握这门语言的面向对象(封装、继承、多态)、面向接口、面向抽象的知识很有必要。

一、面向对象

  1、封装

是面向对象编程中的一个核心概念,它允许将对象的数据(属性)和行为(方法)捆绑在一起,并对外隐藏内部的实现细节。

class Person {
  // 属性
  nationality: string = '中国'; // 国籍
  name?: string;               // 姓名
  age?: number;                // 年龄
  gender?:string

  constructor(name: string, age?: number,gender?:string) {
    this.name = name;
    this.age = age;
    this.gender=gender
  }

  // 方法
  SelfIntroduction(){
    if (this.age !== undefined && this.age !== null && this.age >0) {
        console.log(`My name is ${this.name}, and I am ${this.age} years old this year.`);
    } else {
         console.log(`My name is ${this.name}`);
    }
  }

  Study(){
    console.log(`${this.name}  is studying mathematics diligently.`);
  }
}

let Student:Person=new  Person('小明',undefined,'male')
let Teacher:Person=new Person('宋老师',35,'female')
let Worker:Person=new Person('小王')

Student.SelfIntroduction()
Teacher.SelfIntroduction()
Worker.SelfIntroduction()

Teacher.Study()

上面声明变量时如果不赋值,可以在变量名后面加?,包括对象的方法调用时传参也可以加?,但是如果后面紧跟着参数,该位置如果不传参数必须是undefined。

这样传递参数时可以是变化的。

这里也可以使用展开运算符来解决多参数传递的问题,例如:

function sum(num1:number,num2:number,...others:number[]):number{
  let total=num1+num2
  others.forEach(element => {
    total+=element
  });
  return total
}

console.log(sum(1,2).toString())
console.log(sum(1,2,3,4,5).toString())

当然,如果是多个参数传递,灵活一些应该将参数封装为一个(基于接口的)对象。

声明接口:

interface Para{
  name: string
  age: number
  gender:string
}

传递参数:

  constructor(ParaObj:Para) {
    this.name = ParaObj.name
    this.age = ParaObj.age
    this.gender=ParaObj.gender
  }

实例化:

let Student:Person=new  Person({
  name:'小明',
  age:18,
  gender:'男'
})

正规一些的写法:

interface Para{
  name: string
  age: number
  gender:string
}

class Person {
  // 属性
  protected nationality: string = '中国' // 国籍
  public name: string               // 姓名
  private   _age: number            // 年龄
  private   _gender:string

  constructor(ParaObj:Para) {
    this.name = ParaObj.name
    this._age = ParaObj.age
    this._gender=ParaObj.gender
  }

  get age():number{
    return this._age
  }

  set age(value:number){
    this._age=value
  }

  // 方法
  public SelfIntroduction(){
    if (this.age !== undefined && this.age !== null && this.age >0) {
      console.log(`My name is ${this.name}, and I am ${this.age} years old this year.`);
    } else {
      console.log(`My name is ${this.name}`);
    }
  }
}

let Student:Person=new  Person({
  name:'小明',
  age:18,
  gender:'男'
})

Student.age=25
Student.SelfIntroduction()
console.log(Student.age.toString())

正规一些的写法比较繁琐,但是能有效保护数据,上面的例子中_gender属性没有提供对应的get和set方法,除了初始化能赋值外,外面不能访问。

2、继承
继承允许一个类(子类)继承另一个类(父类)的属性和方法,这有助于代码复用和扩展。

interface Para{
  name: string
  age: number
}

class Person {
  // 属性
  protected nationality: string = '中国' // 国籍
  public name: string               // 姓名
  private   _age: number            // 年龄

  constructor(ParaObj:Para) {
    this.name = ParaObj.name
    this._age = ParaObj.age
  }

  get age():number{
    return this._age
  }

  set age(value:number){
    this._age=value
  }

  // 方法
  public SelfIntroduction(){
    if (this.age !== undefined && this.age !== null && this.age >0) {
      console.log(`My name is ${this.name}, and I am ${this.age} years old this year.`);
    } else {
      console.log(`My name is ${this.name}`);
    }
  }
}

class Student extends Person{
  //重写构造函数
  constructor(ParaObj:Para) {
    super(ParaObj); // 调用父类的构造函数
    //执行其他操作
  }

  Study(){
    console.log(`${this.name} is studying。`);
  }
}

let Student1:Student=new  Student({
  name:'小明',
  age:18,
})

Student1.age=25
Student1.SelfIntroduction()
console.log(Student1.age.toString())

3、多态
多态是指子类可以重写继承自父类的方法,使得同一个方法在不同的子类中可以有不同的实现。

class Person {
  // 属性
  public name: string               // 姓名

  constructor(name:string) {
    this.name = name
  }

  // 方法
  Action(){
    console.log('')
  }
}

class Student extends Person{
  Action(){
    console.log(`${this.name} is studying。`);
  }
}

class Teacher extends Person{
  Action(){
    console.log(`${this.name} is giving a lecture。`);
  }
}

let Student1:Student=new  Student('小明')
Student1.Action()
let Teacher1:Teacher=new Teacher('王老师')
Teacher1.Action()

二、面向接口

⑴当需要定义一个类应该具备的方法签名,但不提供方法的具体实现时,使用接口。
⑵当需要实现代码的松耦合,或者需要一个类遵循某些约定和规范时,使用接口。

interface Shape {
  draw(): void;
}

class Circle implements Shape {
  radius: number;
  constructor(radius: number) {
    this.radius = radius;
  }

  draw(): void {
    console.log(`画一个半径为 ${this.radius} 的圆.`);
  }
}

class Rectangle implements Shape {
  width: number;
  height: number;
  constructor(width: number, height: number) {
    this.width = width;
    this.height = height;
  }

  draw(): void {
    console.log(`画一个宽为 ${this.width} 高为 height ${this.height}的矩形.`);
  }
}

继承多接口的例子:

class Person {
  name: string = '';
  age: number = 0;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  Info(): string {
    return `${this.name}, ${this.age}`;
  }
}

interface Introduce {
  SayHello(): string;
}

interface Work{
  Study():void;
}

class Student extends Person implements Introduce,Work {
  grade: number = 0;

  constructor(name: string, age: number, grade: number) {
    super(name, age);
    this.grade = grade;
  }

  SayHello(): string {
    return `我是${this.grade}年级的学生,名叫${this.name}`;
  }

  Study(){
    console.log(`${this.name} 正在学习`)
  }
}

let Student1:Student = new Student('小明', 18, 9);
console.log(Student1.Info())
console.log(Student1.SayHello());
Student1.Study()

三、面向抽象

⑴当需要在多个子类之间共享代码时,使用抽象类。
⑵当需要强制子类实现某些方法,或者在共性较多的对象间寻求功能上的差异时,使用抽象类。

abstract class Animal {
  name: string;
  constructor(name: string) {
    this.name = name;
  }

  //吃
  abstract eat(food: string): void;

  //睡,有默认实现
  sleep(hours: number): void {
    console.log(`${this.name} is sleeping for ${hours} hours.`);
  }
}

//Dog
class Dog extends Animal {
  constructor(name: string) {
    super(name);
  }

  eat(food: string): void {
    console.log(`${this.name} is eating ${food}.`);
  }
}

//Cat
class Cat extends Animal {
  constructor(name: string) {
    super(name);
  }

  eat(food: string): void {
    console.log(`${this.name} is eating ${food}.`);
  }
}

let dog1:Dog=new  Dog('虎仔')
let cat1:Cat=new Cat('小花')

dog1.eat('骨头')
cat1.eat('猫食')
dog1.sleep(2)

相关文章