You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dependency Injection是否仅适用于接口?抽象类场景算依赖注入吗?

Does Dependency Injection Only Apply to Interface-Based Scenarios?

Great question! This is a super common misconception about dependency injection (DI), so let's break it down clearly:

The Core of Dependency Injection

First, let's get back to what DI actually is. At its heart, DI is a pattern that implements Inversion of Control (IoC)—meaning a class doesn't create its own dependencies; instead, those dependencies are passed (injected) from outside the class. The key principle here is depending on abstractions rather than concrete implementations—but that abstraction doesn't have to be an interface.

Abstract Classes Work Just as Well for DI

Your second scenario (using an abstract class and its subclasses) absolutely counts as dependency injection. Let's use code examples to illustrate:

Interface-Based DI (the common case)

// Interface as the abstraction
public interface IMessageSender {
    void Send(string message);
}

public class EmailSender : IMessageSender {
    public void Send(string message) {
        // Logic to send email
    }
}

// Class receiving the injected dependency
public class NotificationService {
    private readonly IMessageSender _sender;

    // Constructor injection
    public NotificationService(IMessageSender sender) {
        _sender = sender;
    }
}

Abstract Class-Based DI (equally valid)

// Abstract class as the abstraction
public abstract class BaseMessageSender {
    // Abstract method requiring implementation
    public abstract void Send(string message);
    
    // Optional: Default implementation for shared logic
    protected void ValidateMessage(string message) {
        if (string.IsNullOrEmpty(message))
            throw new ArgumentException("Message cannot be empty");
    }
}

public class SmsSender : BaseMessageSender {
    public override void Send(string message) {
        ValidateMessage(message);
        // Logic to send SMS
    }
}

// Class receiving the injected abstract class dependency
public class AlertService {
    private readonly BaseMessageSender _sender;

    // Constructor injection (same pattern as interface)
    public AlertService(BaseMessageSender sender) {
        _sender = sender;
    }
}

In the abstract class example, AlertService depends on the BaseMessageSender abstraction, not the concrete SmsSender. We can swap in any subclass of BaseMessageSender (like a PushNotificationSender) without modifying AlertService—this is exactly the loose coupling that DI is designed to enable.

To go a step further: technically, you can inject a concrete class and still be using DI. For example:

public class ConcreteLogger {
    public void Log(string message) => Console.WriteLine(message);
}

public class ReportService {
    private readonly ConcreteLogger _logger;

    public ReportService(ConcreteLogger logger) {
        _logger = logger;
    }
}

This is still DI because the ConcreteLogger is provided externally, not created inside ReportService. However, this tightens coupling (you can't swap the logger easily), so it's not a best practice. But it's still valid DI.

Final Verdict

Dependency Injection is not limited to interfaces. Any scenario where a class receives its dependencies from an external source—whether those dependencies are interfaces, abstract classes, or even concrete classes—qualifies as DI. The best practice is to depend on abstractions (interfaces or abstract classes) for flexibility, but the pattern itself doesn't restrict you to interfaces.

内容的提问来源于stack exchange,提问作者padrian92

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:50:55