OOP

Câu hỏi phỏng vấn OOP

50+ câu hỏi OOP + SOLID + Design Pattern cho fresher/junior — đáp án ngắn, ví dụ.

A. Tổng quan OOP

1. OOP là gì?

Paradigm mô hình hoá thế giới thực bằng object — gói state + behavior trong 1 entity. 4 tính chất: Encapsulation, Abstraction, Inheritance, Polymorphism.

2. OOP khác Procedural khác Functional?

  • Procedural: tổ chức quanh function/procedure thao tác data.
  • OOP: gom data + function vào object.
  • Functional: tránh state, dùng pure function + immutable data.

Modern languages thường hybrid (C#, TS, Kotlin) — OOP + nhiều feature FP.

3. Class vs Object?

Class = blueprint (template). Object = instance (thực thể) cụ thể từ class.

4. static member là gì?

Member thuộc về class, không phải instance. Truy cập qua tên class. Một bản duy nhất share toàn app.

B. 4 tính chất

5. Kể 4 tính chất OOP và ví dụ?

  1. Encapsulation: che giấu state, expose API có validation. Ví dụ BankAccount ẩn _balance, expose Deposit/Withdraw.
  2. Abstraction: tách "cái gì" khỏi "làm sao". IPaymentGateway không lộ chi tiết HTTP.
  3. Inheritance: Dog : Animal — reuse + chuyên biệt hoá.
  4. Polymorphism: Animal a = new Dog(); a.Speak() → runtime gọi đúng Dog.Speak().

6. Encapsulation khác Abstraction?

  • Encapsulation = mechanism (private, getter/setter).
  • Abstraction = concept (chỉ expose cái cần thiết).

Encapsulation phục vụ Abstraction. Gộp lại = API đơn giản + an toàn.

7. Inheritance — "is-a" hay "has-a"?

Is-a. Dog IS-A Animal. Có "has-a" → dùng composition, không phải inheritance.

8. Multiple inheritance trong C#/TS?

Cả 2 chỉ kế thừa 1 class, implement nhiều interface. TS có pattern mixin để mô phỏng.

9. Vì sao không hỗ trợ multiple class inheritance?

Tránh diamond problem: 2 base có method cùng tên → con kế thừa cái nào không rõ. Interface không state nên không có vấn đề này.

10. Polymorphism có mấy loại?

  • Compile-time (static): overloading — cùng tên, khác signature.
  • Runtime (dynamic): overriding — virtual/override, vtable.
  • Parametric (generic): code làm việc với nhiều type — học ở Generic.

11. Đa hình runtime hoạt động ra sao?

Qua vtable (virtual method table). Mỗi class lưu pointer tới method virtual. Runtime tra vtable của object thực để gọi đúng method.

12. Overload vs Override?

  • Overload: cùng tên, khác parameter list, trong cùng class, compile-time.
  • Override: redefine method virtual của cha trong con, runtime.

13. virtual, abstract, sealed khác nhau?

  • virtual: cho phép con override.
  • abstract: chỉ khai báo, con bắt buộc implement. Class chứa abstract member → class phải abstract.
  • sealed (C#) / final (Java/Kotlin): không cho kế thừa / override tiếp.

C. Interface & Abstract class

14. Interface vs Abstract class?

InterfaceAbstract class
Multiple inheritance
Field/state
Constructor
Default methodC# 8+ có
Mục đíchCapabilityBản chất

15. Khi nào dùng interface, khi nào abstract class?

  • Share code (method body, field) → abstract class.
  • Share contract (hợp đồng) → interface.
  • Multiple inheritance → interface.

16. Default interface method (C# 8+) là gì?

Interface có method với body, làm fallback. Class implement có thể override hoặc không. Hữu ích để thêm member mà không break existing impl.

17. Class có thể vừa kế thừa class vừa implement interface?

Có. Cú pháp: class A : BaseClass, IInterface1, IInterface2.

18. Explicit interface implementation?

Khi 2 interface có method trùng tên cần impl khác nhau:

class Logger : IConsoleLog, IFileLog {
    void IConsoleLog.Log(string m) {}
    void IFileLog.Log(string m) {}
}

D. SOLID

19. SOLID là gì?

5 nguyên lý thiết kế OOP của Robert C. Martin: Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, Dependency Inversion.

20. Single Responsibility — ví dụ?

Class chỉ 1 lý do thay đổi. ❌ Order ôm Calculate + Save + SendEmail. ✅ Tách Order (state), OrderCalculator, OrderRepository, OrderEmailService.

21. Open/Closed — ví dụ?

Mở mở rộng, đóng sửa. ❌ if shape is Circle...else if Square... mỗi shape mới phải sửa. ✅ abstract Shape.Area(), mỗi shape là 1 class.

22. Liskov Substitution — ví dụ vi phạm?

Penguin extends Bird, Bird có Fly() → Penguin throw. Caller có List<Bird> gọi Fly() → crash với Penguin. Fix: tách IFlyable interface.

23. Vì sao Square : Rectangle vi phạm LSP?

Caller set width, height độc lập (Rectangle), assume Area = w * h. Square override setter làm w = h → phá assumption. Fix: 2 class không kế thừa nhau.

24. Interface Segregation — ví dụ?

IWorker { Work, Eat, Sleep } — Robot phải throw Eat. ✅ Tách IWorkable, IFeedable, IRestable. Robot chỉ implement IWorkable.

25. Dependency Inversion — ví dụ?

OrderService new EmailService() gắn cứng. ✅ Depend INotificationService, inject qua constructor. Đổi sang SMS chỉ cần đổi binding container.

26. DIP vs DI vs IoC?

  • DIP: nguyên lý (depend abstraction).
  • IoC: nguyên lý lớn hơn (đảo control flow, framework gọi code bạn).
  • DI: kỹ thuật thực thi DIP/IoC (constructor injection, container).

27. SOLID nguyên lý nào quan trọng nhất cho fresher?

  • SRP: dễ hiểu nhất, áp dụng ngay được.
  • DIP: gặp hằng ngày khi viết ASP.NET Core / NestJS.

28. Khi nào KHÔNG áp dụng SOLID?

Script nhỏ, prototype, throwaway code. Lạm dụng → over-engineering.

E. Composition vs Inheritance

29. "Favor composition over inheritance" — vì sao?

Inheritance: ràng buộc behavior chặt (LSP, fragile base class). Composition: linh hoạt, dễ swap, dễ test. Hierarchy sâu > 3 cấp thường là code smell.

30. Composition khác Aggregation khác Association?

  • Association: 2 class biết nhau (User và Order).
  • Aggregation: has-a yếu, sống độc lập (Library has Books).
  • Composition: has-a mạnh, vòng đời gắn liền (House has Rooms — phá House thì Room mất).

31. Cho ví dụ Composition?

Car chứa IEngine. Engine sống độc lập. Đổi GasEngineElectricEngine không động Car.

F. Design Pattern — Creational

32. Singleton — implement thread-safe?

public sealed class S {
    private static readonly Lazy<S> _i = new(() => new S());
    public static S Instance => _i.Value;
    private S() {}
}

Lazy<T> lo lazy + thread-safe.

33. Singleton lạm dụng có hại gì?

Global state → khó test (test này ảnh hưởng test kia), hidden dependency, khó parallel. Modern app dùng DI container Singleton lifetime.

34. Factory pattern dùng khi nào?

Tạo object có logic phức tạp, hoặc concrete class quyết runtime. Ví dụ IShape Create(string type).

35. Builder vs Constructor với nhiều parameter?

Builder: fluent, optional dễ skip, tên rõ. Constructor 10 parameter khó đọc, dễ nhầm thứ tự.

36. Prototype pattern?

Clone object hiện có thay vì new — khi tạo object expensive. C# có ICloneable nhưng khuyên dùng deep copy thủ công.

G. Design Pattern — Structural

37. Adapter — ví dụ thực tế?

Wrap legacy OldPaymentGateway.DoPayment(double) thành IPaymentService.ChargeAsync(decimal). Service chỉ thấy interface mới.

38. Decorator — ví dụ?

SimpleCoffee → wrap MilkDecorator → wrap CaramelDecorator. Mỗi cấp add cost + description. Stream chain trong .NET: FileStreamBufferedStreamCryptoStream.

39. Facade — ví dụ trong .NET?

services.AddDbContext(), app.MapControllers() — wrap nhiều setup phức tạp thành 1 dòng.

40. Proxy pattern?

Object đứng giữa client và target — kiểm soát truy cập, lazy load, caching, logging. EF Core lazy loading proxy là Proxy pattern.

H. Design Pattern — Behavioral

41. Strategy — ví dụ?

IDiscountStrategy với NoDiscount, TenPercent, StudentDiscount. Cart inject strategy, đổi runtime.

42. Strategy khác State pattern?

  • Strategy: client chọn algorithm.
  • State: object tự đổi state nội bộ, behavior thay đổi theo state.

43. Observer — .NET implement ra sao?

Built-in qua event keyword + EventHandler. Hoặc IObservable<T> / IObserver<T> (Reactive Extensions).

44. Observer vs Pub/Sub?

  • Observer: subject biết observer (in-process).
  • Pub/Sub: message broker giữa publisher và subscriber (cross-process).

45. Command pattern — ứng dụng?

Undo/redo trong editor, transaction, MediatR (CQRS).

46. Template Method?

Abstract class định nghĩa skeleton thuật toán, subclass override các bước cụ thể. Ví dụ DataExporter.Export() gọi LoadData → Transform → Format → Write, mỗi subclass override 3 step đầu.

47. Chain of Responsibility?

Middleware pipeline ASP.NET Core, Express.js — mỗi handler có thể xử lý hoặc pass tiếp.

I. Repository, Unit of Work, DDD

48. Repository pattern — vì sao dùng?

Tách data access khỏi business. Service không biết SQL/Mongo, chỉ thấy IUserRepository. Dễ test (mock), dễ swap DB.

49. Repository với EF Core — có thừa không?

Tranh cãi. EF Core đã là Repository + UoW. Nếu chỉ wrap _ctx.Users.Where(...) → thừa. Nếu có logic query đặc thù tái sử dụng → cần.

50. Unit of Work là gì?

Nhóm nhiều thao tác DB thành 1 transaction. EF Core DbContext chính là UoW — track changes, SaveChanges commit hết.

51. Aggregate Root (DDD)?

Entity đại diện cho 1 cluster — mọi thao tác đi qua nó. Ví dụ Order là root, OrderItem chỉ truy cập qua Order. Đảm bảo invariant.

J. Anti-pattern

52. God class?

Class 2000 dòng làm mọi thứ. Vi phạm SRP. Fix: tách theo trách nhiệm.

53. Anemic Domain Model?

Entity chỉ có get/set, mọi logic ở service. OK cho DTO/CRUD; không tốt cho domain phức tạp — nên có logic trong entity (Rich Domain).

54. Service Locator vs DI?

  • Service Locator: code tự Locator.Get<IFoo>() — hide dependency.
  • DI: inject qua constructor — dependency rõ ràng.

DI tốt hơn — dependency là 1 phần API.

55. "Reinventing the wheel"?

Tự viết lại feature framework đã có (caching, logging, validation) thay vì dùng built-in. Mất thời gian, dễ bug.

K. Câu trick

56. static method có thể override không?

Không ở C# (static thuộc class, không qua vtable). Java cho phép "hiding" nhưng không phải override thật.

57. Constructor có thể virtual không?

Không. Constructor chạy khi object chưa tồn tại đầy đủ → không có vtable lookup.

58. Abstract class có thể không có abstract method?

Có. Vẫn không instantiate được vì marked abstract. Dùng để ép luôn kế thừa.

59. Interface có thể chứa constant không?

C# 8+ có (default member, static field). Java luôn cho. Best practice: hiếm dùng — constant thuộc enum hoặc static class.

60. Override Equals rồi có cần override GetHashCode?

Có. Hợp đồng: a.Equals(b) true → a.GetHashCode() == b.GetHashCode(). Vi phạm → Dictionary/HashSet hoạt động sai.

61. == với class — so sánh gì?

Default: reference. Override hoặc dùng record (C# 9+) → so sánh value.

62. Diamond problem giải quyết sao trong C#?

Interface default member: nếu 2 base interface có cùng method default → class phải implement explicit để chọn hoặc viết riêng.

Tiếp theo chủ đề: Generic

© 2026 .NET Fresher Guide. All rights reserved.

Về Trang Web

Hướng dẫn toàn diện để chuẩn bị phỏng vấn vị trí .NET Fresher với nội dung từ lý thuyết đến thực hành.