Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

ความแตกต่างระหว่าง Abstract Class และ Interface ใน C#

ความแตกต่างหลัก

คุณสมบัติAbstract ClassInterface
Implementationมีได้ทั้ง Abstract และ Concrete MembersC# 8-: Signature เท่านั้น C# 8+: Default Implementation ได้
InheritanceSingle Inheritance (class A : Base)Multiple Implementation (class A : I1, I2)
Constructorมีได้ (Protected/Public)ไม่มี
Fields/Stateมีได้ (Instance/Static Fields)ไม่มี Instance Fields (C# 8+ มี Static Fields)
Access Modifiersทุกอย่าง (private, protected, public, internal...)C# 8-: public เท่านั้น C# 8+: private, protected, internal, static
Performanceเร็วกว่า (Direct Call/Non-virtual)ช้ากว่าเล็กน้อย (Interface Dispatch)
Versioningเพิ่ม Member ได้ (Non-breaking)C# 8-: Breaking Change C# 8+: Default Impl = Non-breaking
Usage"Is-A" Relationship, Shared Implementation"Can-Do" Contract, Capability

Abstract Class - ตัวอย่าง


public abstract class Animal
{
    // State (Fields)
    public string Name { get; set; }
    public int Age { get; protected set; }
    
    // Constructor
    protected Animal(string name)
    {
        Name = name;
    }
    
    // Concrete Method (Shared Implementation)
    public void Eat()
    {
        Console.WriteLine($"{Name} is eating...");
    }
    
    // Abstract Method (Must Override)
    public abstract void MakeSound();
    
    // Virtual Method (Can Override)
    public virtual void Sleep()
    {
        Console.WriteLine($"{Name} is sleeping...");
    }
}

public class Dog : Animal
{
    public Dog(string name) : base(name) { }
    
    public override void MakeSound()
    {
        Console.WriteLine("Woof!");
    }
    
    public override void Sleep()
    {
        base.Sleep(); // Call Base
        Console.WriteLine("...dreaming of bones");
    }
}

Interface - ตัวอย่าง (C# 8+ Features)


public interface IAnimal
{
    // Contract (Implicitly Public)
    string Name { get; set; }
    void MakeSound();
    
    // Default Implementation (C# 8+)
    void Eat()
    {
        Console.WriteLine($"{Name} is eating...");
    }
    
    // Static Members (C# 8+)
    static int Count { get; set; }
    
    // Private Helper (C# 8+)
    private void Log(string msg) => Console.WriteLine($"[LOG] {msg}");
    
    // Protected (C# 8+) - For Implementers
    protected virtual void OnSoundMade() { }
}

public class Cat : IAnimal
{
    public string Name { get; set; }
    
    public void MakeSound()
    {
        Console.WriteLine("Meow!");
        OnSoundMade(); // Can Call Protected
    }
}

Multiple Interfaces vs Single Abstract


// Class สามารถ Implement Interfaces หลายตัว
public class FlyingFish : IFly, ISwim, IAnimal
{
    // Implement ทั้ง 3 Interfaces
    public void Fly() { ... }
    public void Swim() { ... }
    public void MakeSound() { ... }
}

// แต่ Extend Abstract Class ได้เพียง 1 ตัว
// public class FlyingFish : Animal, IFly // ❌ Error: Multiple Base Classes
public class FlyingFish : Animal, IFly // ✅ OK: 1 Base Class + Interfaces
{
    // ...
}

Pattern: Abstract Class + Interface (Best of Both)


// Interface = Contract
public interface IRepository
{
    T GetById(int id);
    void Save(T entity);
}

// Abstract Base = Shared Implementation
public abstract class RepositoryBase : IRepository
{
    protected readonly DbContext Context;
    
    protected RepositoryBase(DbContext context)
    {
        Context = context;
    }
    
    // Shared Implementation
    public virtual T GetById(int id) => Context.Set().Find(id);
    public virtual void Save(T entity) => Context.Set().Add(entity);
    
    // Abstract - Force Implement
    public abstract void Delete(T entity);
}

// Concrete
public class UserRepository : RepositoryBase, IRepository
{
    public UserRepository(DbContext context) : base(context) { }
    
    public override void Delete(User entity) => Context.Users.Remove(entity);
}

Decision Guide

ต้องการอะไร?                    ใช้ตัวไหน?
────────────────────────────────────────────────
Shared Code/State ระหว่าง Related Types  Abstract Class
Multiple Implementations / Capabilities  Interface
Need Constructor / Fields               Abstract Class
Plugin/Extensibility Model              Interface
Versioning (Add Methods Later)          Interface (C# 8+ Default Impl)
Simple Contract / Marker                Interface
Framework Base Class                    Abstract Class

Modern C#: Records + Interfaces


// Data Contract
public interface IUserDto
{
    string Name { get; }
    string Email { get; }
}

// Implementation as Record (Immutable, Value Equality)
public record UserDto(string Name, string Email) : IUserDto;

// Usage
IUserDto user = new UserDto("John", "john@email.com");