← Назад к вопросам

В чем разница между перегрузкой метода и переопределением метода?

1.3 Junior🔥 131 комментариев
#TypeScript#ООП

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI28 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между перегрузкой метода и переопределением метода

Переопределение метода (Method Overriding)

Переопределение — это когда подкласс переопределяет метод родительского класса.

class Animal {
  speak(): string {
    return "Some sound";
  }
}

class Dog extends Animal {
  speak(): string {
    return "Woof!"; // переопределяем метод родителя
  }
}

const dog = new Dog();
console.log(dog.speak()); // "Woof!"

Особенности переопределения:

  • Один метод с одной сигнатурой
  • Изменяет реализацию в подклассе
  • Используется для полиморфизма
  • Наследование и иерархия классов
class Vehicle {
  move(): void {
    console.log("Moving...");
  }
}

class Car extends Vehicle {
  move(): void {
    console.log("Driving on road");
  }
}

class Boat extends Vehicle {
  move(): void {
    console.log("Sailing on water");
  }
}

function startVehicle(vehicle: Vehicle) {
  vehicle.move(); // вызовется соответствующий метод
}

startVehicle(new Car()); // "Driving on road"
startVehicle(new Boat()); // "Sailing on water"

Перегрузка метода (Method Overloading)

Перегрузка — это когда один метод может вызваться с разными типами или количеством параметров.

Осторожно: JavaScript не поддерживает истинную перегрузку! Но TypeScript имеет синтаксис для перегрузки сигнатур:

// Объявляем перегруженные сигнатуры
function add(a: number, b: number): number;
function add(a: string, b: string): string;

// Реальная реализация
function add(a: number | string, b: number | string): number | string {
  if (typeof a === number && typeof b === number) {
    return a + b; // сумма чисел
  }
  return String(a) + String(b); // конкатенация строк
}

console.log(add(5, 3));      // 8
console.log(add("Hello", "World")); // "HelloWorld"

В классах:

class Calculator {
  // Перегруженные сигнатуры
  multiply(a: number, b: number): number;
  multiply(a: string, b: number): string;
  
  // Реализация
  multiply(a: number | string, b: number): number | string {
    if (typeof a === number) {
      return a * b;
    }
    return a.repeat(b);
  }
}

const calc = new Calculator();
console.log(calc.multiply(3, 4));      // 12
console.log(calc.multiply("ab", 3));   // "ababab"

Отличия в таблице

АспектПереопределениеПерегрузка
ИерархияПодкласс vs родительОдин класс
СигнатурыОдна сигнатураРазные сигнатуры
ПараметрыОдинаковыеРазные (тип/кол-во)
Возвращаемый типМожет быть ковариантнымМожет быть разным
ПолиморфизмДинамический (runtime)Статический (compile-time)
Языковая поддержкаJavaScript + TypeScriptTypeScript (только типы)

Полиморфизм

Переопределение обеспечивает runtime полиморфизм:

class Shape {
  area(): number {
    return 0;
  }
}

class Circle extends Shape {
  constructor(private radius: number) { super(); }
  
  area(): number {
    return Math.PI * this.radius * this.radius;
  }
}

class Square extends Shape {
  constructor(private side: number) { super(); }
  
  area(): number {
    return this.side * this.side;
  }
}

const shapes: Shape[] = [
  new Circle(5),
  new Square(4),
  new Circle(3)
];

// Вызываем area() — вызывается нужный метод
shapes.forEach(shape => {
  console.log(shape.area());
});
// 78.54...
// 16
// 28.27...

Перегрузка обеспечивает compile-time типизацию:

function format(value: number): string;
function format(value: Date): string;
function format(value: boolean): string;

function format(value: any): string {
  if (typeof value === number) {
    return value.toFixed(2);
  }
  if (value instanceof Date) {
    return value.toLocaleDateString();
  }
  return String(value);
}

const num = 3.14159;
const formatted = format(num); // TypeScript знает, что это string

Практические примеры

Переопределение — разные реализации:

interface PaymentProcessor {
  process(amount: number): Promise<void>;
}

class CreditCardProcessor implements PaymentProcessor {
  async process(amount: number): Promise<void> {
    // обработка кредитной карты
    console.log(`Processing ${amount} via credit card`);
  }
}

class PayPalProcessor implements PaymentProcessor {
  async process(amount: number): Promise<void> {
    // обработка PayPal
    console.log(`Processing ${amount} via PayPal`);
  }
}

async function checkout(processor: PaymentProcessor, amount: number) {
  await processor.process(amount); // вызовется нужный метод
}

await checkout(new CreditCardProcessor(), 100);
await checkout(new PayPalProcessor(), 100);

Перегрузка — гибкий API:

function fetch(url: string): Promise<Response>;
function fetch(url: string, options: RequestInit): Promise<Response>;

function fetch(url: string, options?: RequestInit): Promise<Response> {
  // реальная реализация
  return window.fetch(url, options);
}

// Оба варианта работают
await fetch(/api/data);
await fetch(/api/data, { method: POST, body: JSON.stringify({}) });

SOLID принципы

Переопределение связано с Liskov Substitution Principle:

// Правильно: подклассы заменяемы
function useShape(shape: Shape) {
  console.log(shape.area()); // работает для любого Shape
}

useShape(new Circle(5));
useShape(new Square(4));

Перегрузка связана с Interface Segregation:

// Правильно: разные сигнатуры для разных использований
function parse(json: string): any;
function parse(json: string, reviver: (k: string, v: any) => any): any;

function parse(json: string, reviver?: (k: string, v: any) => any) {
  return JSON.parse(json, reviver);
}

Когда использовать

Переопределение для:

  • Иерархии классов
  • Полиморфного поведения
  • Реализации интерфейсов
  • Специализации подклассов

Перегрузка для:

  • Гибких APIs с разными параметрами
  • Лучшей типизации (type safety)
  • Одной логической операции с разными входами

Заключение

Переопределение метода — это механизм наследования, позволяющий подклассам изменять поведение родителя. Перегрузка метода — это синтаксис для определения нескольких сигнатур одного метода. В JavaScript не поддерживается истинная перегрузка, но TypeScript обеспечивает типизацию для имитации этого поведения. Оба механизма важны для создания гибких, масштабируемых приложений.

В чем разница между перегрузкой метода и переопределением метода? | PrepBro