JavaScript 类继承
继承是面向对象编程的核心概念之一,它允许我们创建新的类来扩展现有类的功能。JavaScript 通过 extends 关键字支持类继承,使得代码重用和层次化设计变得更加容易。在本章节中,我们将深入学习 JavaScript 中的类继承机制。
什么是继承
继承允许一个类(子类)获取另一个类(父类)的属性和方法。这种机制提供了以下优势:
- 代码重用:避免重复编写相同的代码
- 层次化设计:建立清晰的类层次结构
- 扩展性:可以在不修改原有代码的情况下扩展功能
- 多态性:同一接口可以有不同的实现
基本继承语法
extends 关键字
javascript
// 父类(基类)
class Animal {
constructor(name, species) {
this.name = name;
this.species = species;
}
speak() {
return `${this.name} 发出声音`;
}
move() {
return `${this.name} 在移动`;
}
getInfo() {
return `我是${this.species},名叫${this.name}`;
}
}
// 子类(派生类)
class Dog extends Animal {
constructor(name, breed) {
super(name, "狗"); // 调用父类构造函数
this.breed = breed;
}
// 重写父类方法
speak() {
return `${this.name} 汪汪叫`;
}
// 子类特有方法
fetch() {
return `${this.name} 去捡球`;
}
// 扩展父类方法
getInfo() {
return `${super.getInfo()},品种是${this.breed}`;
}
}
class Cat extends Animal {
constructor(name, color) {
super(name, "猫");
this.color = color;
}
speak() {
return `${this.name} 喵喵叫`;
}
climb() {
return `${this.name} 爬树`;
}
getInfo() {
return `${super.getInfo()},毛色是${this.color}`;
}
}
// 使用示例
const dog = new Dog("旺财", "金毛");
const cat = new Cat("咪咪", "橘色");
console.log(dog.speak()); // "旺财 汪汪叫"
console.log(dog.move()); // "旺财 在移动"(继承自父类)
console.log(dog.fetch()); // "旺财 去捡球"
console.log(dog.getInfo()); // "我是狗,名叫旺财,品种是金毛"
console.log(cat.speak()); // "咪咪 喵喵叫"
console.log(cat.climb()); // "咪咪 爬树"
console.log(cat.getInfo()); // "我是猫,名叫咪咪,毛色是橘色"super 关键字
调用父类构造函数
javascript
class Vehicle {
constructor(brand, model, year) {
this.brand = brand;
this.model = model;
this.year = year;
this.isRunning = false;
}
start() {
this.isRunning = true;
return `${this.brand} ${this.model} 启动了`;
}
stop() {
this.isRunning = false;
return `${this.brand} ${this.model} 停止了`;
}
getInfo() {
return `${this.year} ${this.brand} ${this.model}`;
}
}
class Car extends Vehicle {
constructor(brand, model, year, doors) {
super(brand, model, year); // 必须在使用 this 之前调用
this.doors = doors;
this.fuel = 100;
}
drive(distance) {
if (!this.isRunning) {
return "请先启动车辆";
}
const fuelConsumed = distance * 0.1;
if (this.fuel < fuelConsumed) {
return "燃油不足";
}
this.fuel -= fuelConsumed;
return `行驶了 ${distance} 公里,剩余燃油 ${this.fuel.toFixed(1)}%`;
}
refuel(amount) {
this.fuel = Math.min(100, this.fuel + amount);
return `加油 ${amount}%,当前燃油 ${this.fuel}%`;
}
getInfo() {
return `${super.getInfo()} (${this.doors}门)`;
}
}
class Motorcycle extends Vehicle {
constructor(brand, model, year, engineSize) {
super(brand, model, year);
this.engineSize = engineSize; // cc
this.speed = 0;
}
accelerate(speed) {
if (!this.isRunning) {
return "请先启动车辆";
}
this.speed = Math.min(200, speed);
return `加速到 ${this.speed} km/h`;
}
brake() {
this.speed = 0;
return "刹车";
}
getInfo() {
return `${super.getInfo()} (${this.engineSize}cc)`;
}
}
// 使用示例
const car = new Car("丰田", "卡罗拉", 2023, 4);
console.log(car.start()); // "丰田 卡罗拉 启动了"
console.log(car.drive(50)); // "行驶了 50 公里,剩余燃油 95.0%"
console.log(car.refuel(10)); // "加油 10%,当前燃油 100%"
console.log(car.getInfo()); // "2023 丰田 卡罗拉 (4门)"
const motorcycle = new Motorcycle("本田", "CBR", 2023, 600);
console.log(motorcycle.start()); // "本田 CBR 启动了"
console.log(motorcycle.accelerate(120)); // "加速到 120 km/h"
console.log(motorcycle.brake()); // "刹车"
console.log(motorcycle.getInfo()); // "2023 本田 CBR (600cc)"调用父类方法
javascript
class Shape {
constructor(color) {
this.color = color;
}
getArea() {
return 0;
}
getPerimeter() {
return 0;
}
getDescription() {
return `这是一个${this.color}的图形`;
}
getInfo() {
return {
type: this.constructor.name,
color: this.color,
area: this.getArea(),
perimeter: this.getPerimeter()
};
}
}
class Rectangle extends Shape {
constructor(color, width, height) {
super(color);
this.width = width;
this.height = height;
}
getArea() {
return this.width * this.height;
}
getPerimeter() {
return 2 * (this.width + this.height);
}
getDescription() {
return `${super.getDescription()},尺寸为 ${this.width}x${this.height}`;
}
isSquare() {
return this.width === this.height;
}
}
class Circle extends Shape {
constructor(color, radius) {
super(color);
this.radius = radius;
}
getArea() {
return Math.PI * this.radius * this.radius;
}
getPerimeter() {
return 2 * Math.PI * this.radius;
}
getDescription() {
return `${super.getDescription()},半径为 ${this.radius}`;
}
getDiameter() {
return this.radius * 2;
}
}
// 使用示例
const rectangle = new Rectangle("红色", 10, 5);
const circle = new Circle("蓝色", 3);
console.log(rectangle.getDescription());
// "这是一个红色的图形,尺寸为 10x5"
console.log(rectangle.getInfo());
// { type: "Rectangle", color: "红色", area: 50, perimeter: 30 }
console.log(circle.getDescription());
// "这是一个蓝色的图形,半径为 3"
console.log(circle.getInfo());
// { type: "Circle", color: "蓝色", area: 28.274333882308138, perimeter: 18.84955592153876 }多层继承
javascript
// 基类
class Animal {
constructor(name) {
this.name = name;
this.energy = 100;
}
eat(food) {
this.energy += 10;
return `${this.name} 吃了 ${food},能量增加到 ${this.energy}`;
}
sleep() {
this.energy = 100;
return `${this.name} 睡觉了,能量恢复到 ${this.energy}`;
}
getInfo() {
return `${this.name} (能量: ${this.energy})`;
}
}
// 第一层继承
class Mammal extends Animal {
constructor(name, furColor) {
super(name);
this.furColor = furColor;
this.bodyTemperature = 37;
}
regulateTemperature() {
return `${this.name} 调节体温到 ${this.bodyTemperature}°C`;
}
getInfo() {
return `${super.getInfo()} [哺乳动物,毛色: ${this.furColor}]`;
}
}
// 第二层继承
class Dog extends Mammal {
constructor(name, furColor, breed) {
super(name, furColor);
this.breed = breed;
this.tricks = [];
}
bark() {
this.energy -= 5;
return `${this.name} 汪汪叫 (能量: ${this.energy})`;
}
learnTrick(trick) {
this.tricks.push(trick);
return `${this.name} 学会了 ${trick}`;
}
performTrick() {
if (this.tricks.length === 0) {
return `${this.name} 还没有学会任何技巧`;
}
if (this.energy < 20) {
return `${this.name} 太累了,需要休息`;
}
const trick = this.tricks[Math.floor(Math.random() * this.tricks.length)];
this.energy -= 20;
return `${this.name} 表演了 ${trick} (能量: ${this.energy})`;
}
getInfo() {
return `${super.getInfo()} [品种: ${this.breed}, 技巧: ${this.tricks.join(", ")}]`;
}
}
// 第二层继承
class Cat extends Mammal {
constructor(name, furColor, pattern) {
super(name, furColor);
this.pattern = pattern;
this.lives = 9;
}
meow() {
this.energy -= 3;
return `${this.name} 喵喵叫 (能量: ${this.energy})`;
}
climb() {
if (this.energy < 15) {
return `${this.name} 太累了,无法爬树`;
}
this.energy -= 15;
return `${this.name} 爬上了树 (能量: ${this.energy})`;
}
loseLife() {
if (this.lives > 0) {
this.lives--;
this.energy = 100; // 复活后恢复能量
return `${this.name} 失去了一条命,还剩 ${this.lives} 条命`;
}
return `${this.name} 已经没有命了`;
}
getInfo() {
return `${super.getInfo()} [花纹: ${this.pattern}, 剩余生命: ${this.lives}]`;
}
}
// 使用示例
const dog = new Dog("旺财", "金色", "金毛");
const cat = new Cat("咪咪", "灰色", "条纹");
console.log(dog.eat("狗粮")); // "旺财 吃了 狗粮,能量增加到 110"
console.log(dog.bark()); // "旺财 汪汪叫 (能量: 105)"
console.log(dog.learnTrick("握手")); // "旺财 学会了 握手"
console.log(dog.learnTrick("坐下")); // "旺财 学会了 坐下"
console.log(dog.performTrick()); // "旺财 表演了 握手 (能量: 85)"
console.log(cat.eat("鱼")); // "咪咪 吃了 鱼,能量增加到 110"
console.log(cat.meow()); // "咪咪 喵喵叫 (能量: 107)"
console.log(cat.climb()); // "咪咪 爬上了树 (能量: 92)"
console.log(dog.getInfo());
console.log(cat.getInfo());方法重写和多态
方法重写
javascript
class PaymentMethod {
constructor(name) {
this.name = name;
}
processPayment(amount) {
return `使用 ${this.name} 支付 ¥${amount}`;
}
validate() {
return true;
}
getFee(amount) {
return 0;
}
}
class CreditCard extends PaymentMethod {
constructor(name, cardNumber) {
super(name);
this.cardNumber = cardNumber;
this.limit = 50000;
this.balance = 0;
}
// 重写父类方法
processPayment(amount) {
if (!this.validate()) {
throw new Error("支付验证失败");
}
const totalAmount = amount + this.getFee(amount);
if (this.balance + totalAmount > this.limit) {
throw new Error("超出信用额度");
}
this.balance += totalAmount;
return `信用卡支付成功: ¥${amount} (手续费: ¥${this.getFee(amount)})`;
}
validate() {
// 简化的信用卡验证
return this.cardNumber && this.cardNumber.length === 16;
}
getFee(amount) {
return amount * 0.02; // 2% 手续费
}
getAvailableCredit() {
return this.limit - this.balance;
}
}
class Alipay extends PaymentMethod {
constructor(name, account) {
super(name);
this.account = account;
this.balance = 10000; // 账户余额
}
processPayment(amount) {
if (!this.validate()) {
throw new Error("支付验证失败");
}
const totalAmount = amount + this.getFee(amount);
if (this.balance < totalAmount) {
throw new Error("余额不足");
}
this.balance -= totalAmount;
return `支付宝支付成功: ¥${amount} (手续费: ¥${this.getFee(amount)})`;
}
validate() {
return this.account && this.account.includes("@");
}
getFee(amount) {
return amount > 2000 ? amount * 0.001 : 0; // 超过2000元收0.1%手续费
}
recharge(amount) {
this.balance += amount;
return `充值成功: ¥${amount},当前余额: ¥${this.balance}`;
}
}
class WeChatPay extends PaymentMethod {
constructor(name, openid) {
super(name);
this.openid = openid;
this.balance = 8000;
}
processPayment(amount) {
if (!this.validate()) {
throw new Error("支付验证失败");
}
const totalAmount = amount + this.getFee(amount);
if (this.balance < totalAmount) {
throw new Error("余额不足");
}
this.balance -= totalAmount;
return `微信支付成功: ¥${amount} (手续费: ¥${this.getFee(amount)})`;
}
validate() {
return this.openid && this.openid.length > 10;
}
getFee(amount) {
return 0; // 微信支付通常无手续费
}
transfer(toUser, amount) {
if (this.balance < amount) {
throw new Error("余额不足");
}
this.balance -= amount;
return `转账成功: 向 ${toUser} 转账 ¥${amount}`;
}
}
// 使用示例
const creditCard = new CreditCard("Visa信用卡", "1234567890123456");
const alipay = new Alipay("支付宝", "user@example.com");
const wechat = new WeChatPay("微信支付", "openid_1234567890");
// 多态性:同一接口,不同实现
const payments = [creditCard, alipay, wechat];
payments.forEach(payment => {
try {
console.log(payment.processPayment(1000));
} catch (error) {
console.log(`${payment.name}: ${error.message}`);
}
});
// 特定方法调用
console.log(creditCard.getAvailableCredit());
console.log(alipay.recharge(5000));
console.log(wechat.transfer("朋友A", 200));继承中的静态方法
javascript
class Database {
constructor(name) {
this.name = name;
this.isConnected = false;
}
connect() {
this.isConnected = true;
return `连接到数据库 ${this.name}`;
}
disconnect() {
this.isConnected = false;
return `断开数据库 ${this.name} 连接`;
}
// 静态方法
static getDefaultConfig() {
return {
host: "localhost",
port: 3306,
timeout: 5000
};
}
static validateConfig(config) {
return config.host && config.port;
}
// 静态属性(ES2022)
static VERSION = "1.0.0";
}
class MySQL extends Database {
constructor(name, config) {
super(name);
this.config = { ...Database.getDefaultConfig(), ...config };
}
connect() {
if (!Database.validateConfig(this.config)) {
throw new Error("数据库配置无效");
}
return `${super.connect()} [MySQL ${MySQL.VERSION}]`;
}
query(sql) {
if (!this.isConnected) {
throw new Error("数据库未连接");
}
return `执行查询: ${sql}`;
}
// 重写静态方法
static getDefaultConfig() {
return {
...super.getDefaultConfig(),
engine: "InnoDB",
charset: "utf8mb4"
};
}
static validateConfig(config) {
return super.validateConfig(config) && config.engine;
}
}
class PostgreSQL extends Database {
constructor(name, config) {
super(name);
this.config = { ...Database.getDefaultConfig(), ...config };
}
connect() {
if (!Database.validateConfig(this.config)) {
throw new Error("数据库配置无效");
}
return `${super.connect()} [PostgreSQL ${PostgreSQL.VERSION}]`;
}
execute(sql) {
if (!this.isConnected) {
throw new Error("数据库未连接");
}
return `执行语句: ${sql}`;
}
static getDefaultConfig() {
return {
...super.getDefaultConfig(),
dialect: "postgres",
pool: { max: 10, min: 0 }
};
}
static validateConfig(config) {
return super.validateConfig(config) && config.dialect;
}
}
// 使用示例
console.log("数据库版本:", Database.VERSION); // "1.0.0"
const mysqlConfig = {
host: "localhost",
port: 3306,
engine: "InnoDB"
};
const pgConfig = {
host: "localhost",
port: 5432,
dialect: "postgres"
};
const mysql = new MySQL("myapp", mysqlConfig);
const postgres = new PostgreSQL("myapp", pgConfig);
console.log(mysql.connect()); // "连接到数据库 myapp [MySQL 1.0.0]"
console.log(mysql.query("SELECT * FROM users")); // "执行查询: SELECT * FROM users"
console.log(postgres.connect()); // "连接到数据库 myapp [PostgreSQL 1.0.0]"
console.log(postgres.execute("SELECT * FROM users")); // "执行语句: SELECT * FROM users"
// 静态方法调用
console.log("MySQL默认配置:", MySQL.getDefaultConfig());
console.log("PostgreSQL默认配置:", PostgreSQL.getDefaultConfig());继承最佳实践
1. 合理设计继承层次
javascript
// 好的设计:清晰的继承层次
class Vehicle {
constructor(brand) {
this.brand = brand;
}
start() {
return `${this.brand} 启动`;
}
}
class LandVehicle extends Vehicle {
constructor(brand, wheels) {
super(brand);
this.wheels = wheels;
}
drive() {
return `${this.brand} 在路上行驶`;
}
}
class WaterVehicle extends Vehicle {
constructor(brand, displacement) {
super(brand);
this.displacement = displacement; // 排水量
}
sail() {
return `${this.brand} 在水上航行`;
}
}
class Car extends LandVehicle {
constructor(brand, doors) {
super(brand, 4);
this.doors = doors;
}
park() {
return `${this.brand} 停车`;
}
}
class Motorcycle extends LandVehicle {
constructor(brand, engineType) {
super(brand, 2);
this.engineType = engineType;
}
wheelie() {
return `${this.brand} 后轮着地`;
}
}
class Boat extends WaterVehicle {
constructor(brand, type) {
super(brand, "中等");
this.type = type; // 艇型
}
anchor() {
return `${this.brand} 抛锚`;
}
}
// 使用示例
const car = new Car("丰田", 4);
const motorcycle = new Motorcycle("本田", "四冲程");
const boat = new Boat("游艇品牌", "游艇");
console.log(car.start()); // "丰田 启动"
console.log(car.drive()); // "丰田 在路上行驶"
console.log(car.park()); // "丰田 停车"
console.log(motorcycle.start()); // "本田 启动"
console.log(motorcycle.drive()); // "本田 在路上行驶"
console.log(motorcycle.wheelie()); // "本田 后轮着地"
console.log(boat.start()); // "游艇品牌 启动"
console.log(boat.sail()); // "游艇品牌 在水上航行"
console.log(boat.anchor()); // "游艇品牌 抛锚"2. 使用组合优于继承
javascript
// 继承方式(不太灵活)
class SmartPhone extends Phone {
constructor(brand, model) {
super(brand, model);
this.apps = [];
this.battery = 100;
}
installApp(app) {
this.apps.push(app);
return `安装应用: ${app}`;
}
runApp(app) {
if (this.battery < 10) {
return "电量不足";
}
this.battery -= 5;
return `运行应用: ${app}`;
}
charge() {
this.battery = 100;
return "充电完成";
}
}
// 组合方式(更灵活)
class Device {
constructor(brand, model) {
this.brand = brand;
this.model = model;
}
powerOn() {
return `${this.brand} ${this.model} 开机`;
}
powerOff() {
return `${this.brand} ${this.model} 关机`;
}
}
class Battery {
constructor(capacity = 100) {
this.capacity = capacity;
this.level = capacity;
}
use(amount) {
this.level = Math.max(0, this.level - amount);
}
charge() {
this.level = this.capacity;
}
getLevel() {
return this.level;
}
isLow() {
return this.level < 20;
}
}
class AppManager {
constructor() {
this.installedApps = [];
}
install(app) {
this.installedApps.push(app);
return `安装应用: ${app}`;
}
uninstall(app) {
this.installedApps = this.installedApps.filter(a => a !== app);
return `卸载应用: ${app}`;
}
getInstalledApps() {
return [...this.installedApps];
}
}
class SmartPhone {
constructor(brand, model) {
this.device = new Device(brand, model);
this.battery = new Battery(100);
this.appManager = new AppManager();
}
powerOn() {
return this.device.powerOn();
}
powerOff() {
return this.device.powerOff();
}
installApp(app) {
return this.appManager.install(app);
}
runApp(app) {
if (this.battery.isLow()) {
return "电量不足,请充电";
}
this.battery.use(5);
return `运行应用: ${app}`;
}
charge() {
this.battery.charge();
return "充电完成";
}
getBatteryLevel() {
return this.battery.getLevel();
}
getInstalledApps() {
return this.appManager.getInstalledApps();
}
}
// 使用示例
const phone = new SmartPhone("苹果", "iPhone 15");
console.log(phone.powerOn()); // "苹果 iPhone 15 开机"
console.log(phone.installApp("微信")); // "安装应用: 微信"
console.log(phone.installApp("支付宝")); // "安装应用: 支付宝"
console.log(phone.runApp("微信")); // "运行应用: 微信"
console.log(phone.getBatteryLevel()); // 95
console.log(phone.getInstalledApps()); // ["微信", "支付宝"]
console.log(phone.charge()); // "充电完成"3. 抽象类和接口模拟
javascript
// 抽象类(模拟)
class Animal {
constructor(name) {
if (this.constructor === Animal) {
throw new Error("不能直接实例化抽象类 Animal");
}
this.name = name;
}
// 抽象方法(需要子类实现)
makeSound() {
throw new Error("抽象方法 makeSound 必须被子类实现");
}
// 具体方法
eat() {
return `${this.name} 在吃东西`;
}
sleep() {
return `${this.name} 在睡觉`;
}
}
class Dog extends Animal {
constructor(name) {
super(name);
}
// 实现抽象方法
makeSound() {
return `${this.name} 汪汪叫`;
}
// 特有方法
fetch() {
return `${this.name} 去捡球`;
}
}
class Cat extends Animal {
constructor(name) {
super(name);
}
// 实现抽象方法
makeSound() {
return `${this.name} 喵喵叫`;
}
// 特有方法
climb() {
return `${this.name} 爬树`;
}
}
// 接口模拟
class Flyable {
fly() {
throw new Error("fly 方法必须被实现");
}
}
class Swimmable {
swim() {
throw new Error("swim 方法必须被实现");
}
}
// 多重继承模拟(通过混入)
class Bird extends Animal {
constructor(name) {
super(name);
}
makeSound() {
return `${this.name} 唧唧喳喳`;
}
}
// 混入 Flyable 功能
Object.assign(Bird.prototype, Flyable.prototype);
Bird.prototype.fly = function() {
return `${this.name} 在天空中飞翔`;
};
class Fish extends Animal {
constructor(name) {
super(name);
}
makeSound() {
return `${this.name} 吐泡泡`;
}
}
// 混入 Swimmable 功能
Object.assign(Fish.prototype, Swimmable.prototype);
Fish.prototype.swim = function() {
return `${this.name} 在水中游泳`;
};
class Duck extends Animal {
constructor(name) {
super(name);
}
makeSound() {
return `${this.name} 嘎嘎叫`;
}
}
// 混入多个接口
Object.assign(Duck.prototype, Flyable.prototype, Swimmable.prototype);
Duck.prototype.fly = function() {
return `${this.name} 飞起来了`;
};
Duck.prototype.swim = function() {
return `${this.name} 在水中游泳`;
};
// 使用示例
try {
// const animal = new Animal("测试"); // 错误:不能直接实例化抽象类
} catch (error) {
console.log(error.message);
}
const dog = new Dog("旺财");
const cat = new Cat("咪咪");
const bird = new Bird("小鸟");
const fish = new Fish("金鱼");
const duck = new Duck("唐老鸭");
console.log(dog.makeSound()); // "旺财 汪汪叫"
console.log(dog.fetch()); // "旺财 去捡球"
console.log(cat.makeSound()); // "咪咪 喵喵叫"
console.log(cat.climb()); // "咪咪 爬树"
console.log(bird.makeSound()); // "小鸟 唧唧喳喳"
console.log(bird.fly()); // "小鸟 在天空中飞翔"
console.log(fish.makeSound()); // "金鱼 吐泡泡"
console.log(fish.swim()); // "金鱼 在水中游泳"
console.log(duck.makeSound()); // "唐老鸭 嘎嘎叫"
console.log(duck.fly()); // "唐老鸭 飞起来了"
console.log(duck.swim()); // "唐老鸭 在水中游泳"实际应用示例
1. 游戏角色系统
javascript
// 基础角色类
class Character {
constructor(name, level = 1) {
this.name = name;
this.level = level;
this.health = 100;
this.maxHealth = 100;
this.mana = 50;
this.maxMana = 50;
this.experience = 0;
this.experienceToNextLevel = 100;
}
takeDamage(damage) {
this.health = Math.max(0, this.health - damage);
return `${this.name} 受到 ${damage} 点伤害,剩余生命值 ${this.health}`;
}
heal(amount) {
this.health = Math.min(this.maxHealth, this.health + amount);
return `${this.name} 恢复 ${amount} 点生命值`;
}
useMana(amount) {
if (this.mana >= amount) {
this.mana -= amount;
return true;
}
return false;
}
restoreMana(amount) {
this.mana = Math.min(this.maxMana, this.mana + amount);
}
gainExperience(exp) {
this.experience += exp;
if (this.experience >= this.experienceToNextLevel) {
return this.levelUp();
}
return `${this.name} 获得 ${exp} 点经验值`;
}
levelUp() {
this.level++;
this.experience -= this.experienceToNextLevel;
this.experienceToNextLevel = Math.floor(this.experienceToNextLevel * 1.5);
this.maxHealth += 20;
this.health = this.maxHealth;
this.maxMana += 10;
this.mana = this.maxMana;
return `${this.name} 升级到 ${this.level} 级!`;
}
isAlive() {
return this.health > 0;
}
getInfo() {
return {
name: this.name,
level: this.level,
health: this.health,
maxHealth: this.maxHealth,
mana: this.mana,
maxMana: this.maxMana,
experience: this.experience,
experienceToNextLevel: this.experienceToNextLevel
};
}
}
// 战士类
class Warrior extends Character {
constructor(name) {
super(name);
this.strength = 20;
this.armor = 5;
}
// 基础攻击
attack(target) {
const damage = this.strength - target.armor;
return target.takeDamage(Math.max(1, damage));
}
// 技能:重击
heavyStrike(target) {
const manaCost = 10;
if (!this.useMana(manaCost)) {
return `${this.name} 魔法值不足`;
}
const damage = (this.strength * 2) - target.armor;
return target.takeDamage(Math.max(1, damage));
}
// 技能:防御姿态
defend() {
this.armor += 3;
return `${this.name} 进入防御姿态,护甲增加`;
}
levelUp() {
const result = super.levelUp();
this.strength += 5;
this.armor += 2;
return result;
}
getInfo() {
return {
...super.getInfo(),
class: "战士",
strength: this.strength,
armor: this.armor
};
}
}
// 法师类
class Mage extends Character {
constructor(name) {
super(name);
this.intelligence = 25;
this.spellPower = 15;
}
// 基础攻击:火球术
fireball(target) {
const manaCost = 15;
if (!this.useMana(manaCost)) {
return `${this.name} 魔法值不足`;
}
const damage = this.spellPower + (this.intelligence * 0.5);
return target.takeDamage(damage);
}
// 技能:治疗术
healSpell(target) {
const manaCost = 20;
if (!this.useMana(manaCost)) {
return `${this.name} 魔法值不足`;
}
const healAmount = this.intelligence;
return target.heal(healAmount);
}
// 技能:魔法护盾
magicShield() {
const manaCost = 25;
if (!this.useMana(manaCost)) {
return `${this.name} 魔法值不足`;
}
this.armor += 10;
return `${this.name} 施放魔法护盾`;
}
levelUp() {
const result = super.levelUp();
this.intelligence += 7;
this.spellPower += 3;
return result;
}
getInfo() {
return {
...super.getInfo(),
class: "法师",
intelligence: this.intelligence,
spellPower: this.spellPower
};
}
}
// 弓箭手类
class Archer extends Character {
constructor(name) {
super(name);
this.dexterity = 18;
this.criticalChance = 0.1; // 10% 暴击率
}
// 基础攻击:射击
shoot(target) {
let damage = this.dexterity;
// 暴击计算
if (Math.random() < this.criticalChance) {
damage *= 2;
return target.takeDamage(damage) + " (暴击!)";
}
return target.takeDamage(damage);
}
// 技能:多重射击
multiShot(targets) {
const manaCost = 20;
if (!this.useMana(manaCost)) {
return `${this.name} 魔法值不足`;
}
const results = [];
const damage = this.dexterity * 0.7;
targets.forEach(target => {
results.push(target.takeDamage(damage));
});
return `${this.name} 发射多重箭:` + results.join(",");
}
// 技能:隐身
stealth() {
const manaCost = 15;
if (!this.useMana(manaCost)) {
return `${this.name} 魔法值不足`;
}
return `${this.name} 进入隐身状态`;
}
levelUp() {
const result = super.levelUp();
this.dexterity += 6;
this.criticalChance += 0.02; // 增加暴击率
return result;
}
getInfo() {
return {
...super.getInfo(),
class: "弓箭手",
dexterity: this.dexterity,
criticalChance: this.criticalChance
};
}
}
// 怪物类
class Monster extends Character {
constructor(name, level, type) {
super(name, level);
this.type = type;
this.expReward = level * 20;
this.goldReward = level * 10;
// 根据等级调整属性
this.maxHealth = 50 + (level * 25);
this.health = this.maxHealth;
this.maxMana = 20 + (level * 10);
this.mana = this.maxMana;
this.strength = 10 + (level * 3);
this.armor = level;
}
attack(target) {
const damage = this.strength - target.armor;
return target.takeDamage(Math.max(1, damage));
}
getInfo() {
return {
...super.getInfo(),
type: this.type,
expReward: this.expReward,
goldReward: this.goldReward
};
}
}
// 使用示例
const warrior = new Warrior("战士张三");
const mage = new Mage("法师李四");
const archer = new Archer("弓箭手王五");
const goblin = new Monster("哥布林", 1, "普通");
const orc = new Monster("兽人", 3, "精英");
// 战斗示例
console.log(warrior.attack(goblin));
console.log(mage.fireball(goblin));
console.log(archer.shoot(goblin));
if (!goblin.isAlive()) {
console.log(warrior.gainExperience(goblin.expReward));
}
console.log(orc.attack(warrior));
console.log(warrior.heavyStrike(orc));
console.log(mage.healSpell(warrior));
console.log("战士信息:", warrior.getInfo());
console.log("法师信息:", mage.getInfo());
console.log("弓箭手信息:", archer.getInfo());2. UI 组件系统
javascript
// 基础组件类
class Component {
constructor(props = {}) {
this.props = props;
this.state = {};
this.children = [];
this.parent = null;
}
setState(newState) {
this.state = { ...this.state, ...newState };
this.render();
}
addChild(child) {
child.parent = this;
this.children.push(child);
}
removeChild(child) {
const index = this.children.indexOf(child);
if (index > -1) {
this.children.splice(index, 1);
child.parent = null;
}
}
// 抽象方法,需要子类实现
render() {
throw new Error("render 方法必须被子类实现");
}
mount(container) {
container.appendChild(this.render());
}
}
// 容器组件
class Container extends Component {
constructor(props) {
super(props);
this.style = props.style || {};
}
render() {
const container = document.createElement(this.props.tagName || "div");
// 应用样式
Object.assign(container.style, this.style);
// 渲染子组件
this.children.forEach(child => {
const childElement = child.render();
container.appendChild(childElement);
});
return container;
}
}
// 文本组件
class Text extends Component {
constructor(props) {
super(props);
this.text = props.text || "";
}
render() {
const textElement = document.createElement("span");
textElement.textContent = this.text;
if (this.props.className) {
textElement.className = this.props.className;
}
return textElement;
}
updateText(newText) {
this.text = newText;
return this.render();
}
}
// 按钮组件
class Button extends Component {
constructor(props) {
super(props);
this.text = props.text || "按钮";
this.disabled = props.disabled || false;
this.onClick = props.onClick || (() => {});
}
render() {
const button = document.createElement("button");
button.textContent = this.text;
button.disabled = this.disabled;
if (this.props.className) {
button.className = this.props.className;
}
// 绑定事件
button.addEventListener("click", this.onClick);
return button;
}
setDisabled(disabled) {
this.disabled = disabled;
return this.render();
}
}
// 输入框组件
class Input extends Component {
constructor(props) {
super(props);
this.value = props.value || "";
this.placeholder = props.placeholder || "";
this.type = props.type || "text";
this.onInput = props.onInput || (() => {});
}
render() {
const input = document.createElement("input");
input.type = this.type;
input.value = this.value;
input.placeholder = this.placeholder;
if (this.props.className) {
input.className = this.props.className;
}
// 绑定事件
input.addEventListener("input", (e) => {
this.value = e.target.value;
this.onInput(e);
});
return input;
}
getValue() {
return this.value;
}
setValue(value) {
this.value = value;
return this.render();
}
}
// 表单组件
class Form extends Container {
constructor(props) {
super({ ...props, tagName: "form" });
this.onSubmit = props.onSubmit || ((e) => e.preventDefault());
}
render() {
const form = super.render();
form.addEventListener("submit", this.onSubmit);
return form;
}
getData() {
const data = {};
// 收集所有输入组件的值
this.children.forEach(child => {
if (child instanceof Input && child.props.name) {
data[child.props.name] = child.getValue();
}
});
return data;
}
}
// 卡片组件
class Card extends Container {
constructor(props) {
super(props);
this.title = props.title || "";
}
render() {
const card = document.createElement("div");
card.className = "card";
// 添加标题
if (this.title) {
const titleElement = document.createElement("h3");
titleElement.textContent = this.title;
card.appendChild(titleElement);
}
// 渲染子组件
this.children.forEach(child => {
const childElement = child.render();
card.appendChild(childElement);
});
return card;
}
}
// 使用示例
const app = new Container({
style: {
padding: "20px",
fontFamily: "Arial, sans-serif"
}
});
const title = new Text({
text: "用户注册表单",
className: "title"
});
const form = new Form({
onSubmit: (e) => {
e.preventDefault();
const formData = form.getData();
console.log("表单数据:", formData);
submitButton.setDisabled(true);
}
});
const nameInput = new Input({
name: "name",
placeholder: "请输入姓名",
onInput: (e) => {
console.log("姓名输入:", e.target.value);
}
});
const emailInput = new Input({
name: "email",
type: "email",
placeholder: "请输入邮箱"
});
const submitButton = new Button({
text: "提交",
onClick: () => {
console.log("按钮被点击");
}
});
// 组装界面
form.addChild(nameInput);
form.addChild(emailInput);
form.addChild(submitButton);
const card = new Card({
title: "注册信息"
});
card.addChild(form);
app.addChild(title);
app.addChild(card);
// 模拟挂载到页面
// app.mount(document.body);
console.log("UI 组件系统示例创建完成");
console.log("组件层次结构:");
console.log("- Container (app)");
console.log(" - Text (title)");
console.log(" - Card (card)");
console.log(" - Form (form)");
console.log(" - Input (nameInput)");
console.log(" - Input (emailInput)");
console.log(" - Button (submitButton)");总结
JavaScript 类继承的核心要点:
- 基本语法:使用 extends 关键字实现继承,super 调用父类
- 构造函数:子类构造函数中必须先调用 super() 再使用 this
- 方法重写:子类可以重写父类方法,使用 super 调用父类方法
- 多层继承:支持多层次的继承结构
- 静态继承:子类继承父类的静态方法和属性
- 多态性:同一接口可以有不同的实现
- 最佳实践:合理设计继承层次,优先使用组合而非继承
- 抽象类:通过抛出错误模拟抽象类和抽象方法
掌握类继承是面向对象编程的重要技能。在下一章节中,我们将学习 JavaScript 的静态方法。