鸿蒙ArkTS中的面向对象编程
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)