实用指南:【C# OOP 入门到精通】从基础概念到 MVC 实战(含 SOLID 原则与完整代码)

news/2025/11/15 19:12:30/文章来源:https://www.cnblogs.com/gccbuaa/p/19226077

在 C# 开发中,面向对象编程(OOP)是构建可维护、可扩展系统的核心思想,尤其在 MVC 框架中,OOP 的封装、继承、多态特性贯穿了 Model 层设计、业务逻辑实现的全过程。本文从基础概念入手,结合企业级实战案例,带您彻底掌握 OOP 的核心用法与设计精髓,代码可直接复制到项目中运行。

在这里插入图片描述

一、OOP 核心概念:从基础到进阶

OOP 的四大核心概念(类与对象、封装、继承、多态)是构建复杂系统的基石,我们从 “是什么” 到 “怎么用” 逐步拆解,每个知识点均配套 MVC 实战场景解析。

1.1 类与对象:代码世界的 “模板与实例”

类是对现实事物的抽象描述(如 “汽车” 的模板),对象是类的具体实例(如 “张三的红色宝马”),二者是 OOP 的基础构成单元。
基础用法:类的定义与对象创建

using System;
// 类(模板):描述汽车的共同属性和行为
public class Car
{
// 字段:存储对象状态(私有字段加下划线前缀,符合C#命名规范)
private string _color;
private string _brand;
// 静态字段:所有Car对象共享(如"汽车总数"计数器)
public static int TotalCarCount { get; private set; }
// 1. 默认构造函数(无参):创建对象时自动调用
public Car()
{
TotalCarCount++; // 每创建一个对象,总数+1
}
// 2. 构造函数重载(带参):简化对象初始化
public Car(string color, string brand) : this() // 调用无参构造函数
{
_color = color;
_brand = brand;
}
// 属性:控制字段访问(公开读取,私有修改)
public string Color => _color;
public string Brand => _brand;
// 方法:定义对象行为
public void Run()
{
Console.WriteLine($"{_brand}{_color})以100km/h行驶");
}
}
// 测试:创建对象(适用框架:.NET Framework 4.5+ / .NET Core 3.1+)
Car car1 = new Car(); // 无参构造初始化
car1 = new Car("黑色", "宝马"); // 带参构造直接赋值
Car car2 = new Car("白色", "奔驰");
Console.WriteLine($"已创建汽车总数:{Car.TotalCarCount}"); // 输出2(静态成员用"类名.成员"调用)
car2.Run(); // 输出:奔驰(白色)以100km/h行驶

进阶细节:静态成员的 MVC 应用场景
静态成员属于类而非对象,适合存储 “类级别的共享数据”,在 MVC 中常用于工具类设计:
示例:DateHelper静态工具类(无需创建对象即可调用)

public static class DateHelper
{
// 静态方法:格式化日期(MVC中View层常用)
public static string FormatDate(DateTime date)
{
return date.ToString("yyyy-MM-dd HH:mm:ss");
}
}
// MVC的Controller中调用
string createTime = DateHelper.FormatDate(DateTime.Now);

类与对象关系可视化

new Car黑色宝马
new Car白色奔驰
Car类模板
car1对象
car2对象
静态成员TotalCarCount=2

【类与对象小结】

  • 类是 “模板”,定义属性和方法;对象是 “实例”,通过new关键字创建。
  • 构造函数重载可满足不同初始化需求,MVC 实体类常用带参构造简化赋值。
  • 静态成员适合工具类场景,避免频繁创建对象造成的性能开销。

1.2 封装:“隐藏细节,暴露接口” 的安全艺术

封装是将数据(字段)和操作数据的方法捆绑,限制外部直接访问数据,仅通过公开接口交互,核心是 “数据安全” 与 “逻辑内聚”。
基础用法:私有字段 + 公开接口

// 封装示例:银行账户(防止余额被随意修改)
public class BankAccount
{
// 只读字段:仅能在构造函数中赋值(如账户所有人不可变更)
private readonly string _accountOwner;
// 私有字段:外部无法直接访问
private decimal _balance;
// 公开属性:仅允许读取,不允许直接修改
public string AccountNumber { get; }
public decimal Balance { get => _balance; private set => _balance = value; }
// 构造函数:初始化只读字段和初始状态
public BankAccount(string accountNumber, string owner)
{
AccountNumber = accountNumber;
_accountOwner = owner;
_balance = 0; // 初始余额为0
}
// 公开方法:存款(含业务校验)
public void Deposit(decimal amount)
{
if (amount <= 0)
throw new ArgumentException("存款金额必须大于0");
Balance += amount; // 内部通过private set修改余额
}
// 公开方法:取款(含异常处理)
public bool Withdraw(decimal amount)
{
if (amount <= 0)
{
Console.WriteLine("取款金额无效");
return false;
}
if (amount > _balance)
{
Console.WriteLine("余额不足");
return false;
}
Balance -= amount;
return true;
}
}
// 测试:封装的安全性
var account = new BankAccount("622202123456789", "张三");
account.Deposit(1000);
bool success = account.Withdraw(300);
if (success) Console.WriteLine($"取款后余额:{account.Balance}"); // 输出700
// account.Balance = 2000; // 错误:Balance的set访问器是private,无法直接修改

MVC 实战:Model 层的数据封装
在 MVC 中,封装是 Model 层的核心设计思想,通过属性校验确保数据合法性:

using System.ComponentModel.DataAnnotations;
// MVC的User实体(封装用户信息与校验逻辑)
public class User
{
private string _password;
[Key] // 标记为主键(对应数据库)
public int Id { get; set; }
[Required(ErrorMessage = "用户名不能为空")] // 数据校验
[StringLength(20, MinimumLength = 3, ErrorMessage = "用户名长度3-20字符")]
public string Username { get; set; }
// 密码封装:外部只能通过方法设置(加密存储)
public string PasswordHash => _password;
// 公开方法:设置密码(含加密逻辑)
public void SetPassword(string password)
{
if (string.IsNullOrEmpty(password) || password.Length < 6)
throw new ValidationException("密码长度不能少于6位");
_password = MD5Encrypt(password); // 模拟加密(实际用System.Security.Cryptography)
}
private string MD5Encrypt(string input)
{
return input.GetHashCode().ToString(); // 简化示例,生产环境用正式加密算法
}
}

【封装小结】

  • 核心原则:“隐藏实现细节,暴露最小接口”,私有字段存数据,公开属性 / 方法控访问。
  • 业务价值:数据校验、安全逻辑(如密码加密)在封装内部实现,避免外部代码混乱。
  • MVC 场景:Model 层通过DataAnnotations和私有字段,确保进入 Controller 的数据合法安全。

1.3 继承:“复用代码,扩展功能” 的高效方式

继承允许创建新类(子类)继承现有类(父类)的属性和方法,实现代码复用,同时可扩展新功能,核心是 “IS-A” 关系(如 “狗是动物”)。
基础用法:子类继承与 base 关键字

// 父类(抽象类):动物(共性)
public abstract class Animal
{
public int Age { get; set; }
// 父类带参构造函数
public Animal(int age)
{
Age = age;
Console.WriteLine($"动物({age}岁)初始化");
}
// 抽象方法:子类必须实现(共性行为的不同实现)
public abstract void MakeSound();
// 普通方法:子类可直接继承(共享功能)
public void Breathe()
{
Console.WriteLine("用肺呼吸");
}
}
// 子类:狗(继承Animal,扩展个性)
public class Dog : Animal
{
public string Nickname { get; set; }
// 子类构造函数:用base调用父类构造
public Dog(string nickname, int age) : base(age)
{
Nickname = nickname;
Console.WriteLine($"狗({nickname}{age}岁)初始化");
}
// 重写抽象方法:实现狗的叫声
public override void MakeSound()
{
Console.WriteLine($"{Nickname}:汪汪叫");
}
// 子类新增方法:扩展父类没有的功能
public void GuardHouse()
{
Console.WriteLine($"{Nickname}正在看家");
}
}
// 密封类:禁止被继承(MVC框架常用)
public sealed class SealedDog : Dog
{
public SealedDog(string nickname, int age) : base(nickname, age) { }
}
// 测试:继承的代码复用
Dog wangcai = new Dog("旺财", 3);
wangcai.Breathe(); // 继承父类方法:用肺呼吸
wangcai.MakeSound(); // 重写方法:旺财:汪汪叫
wangcai.GuardHouse(); // 子类新增方法:旺财正在看家
// public class XiaoWangCai : SealedDog { } // 错误:密封类不能被继承

继承层次可视化

属性
方法
抽象方法
新增方法
Animal抽象类
Dog子类
Cat子类
SealedDog密封子类
Age
Breathe
MakeSound
GuardHouse

MVC 实战:Controller 的继承体系
在 MVC 中,所有控制器都继承自Controller基类,体现继承的代码复用价值:

// MVC的自定义基类(继承自框架Controller)
public class BaseController : Controller
{
// 所有子类共享的功能:用户登录校验
protected bool IsUserLogin()
{
return Session["UserId"] != null; // 校验Session
}
// 权限检查(子类可重写)
protected virtual bool CheckPermission(string permission)
{
var userPermissions = Session["Permissions"] as List<string>;return userPermissions?.Contains(permission) ?? false;}}// 商品控制器(继承自定义基类)public class ProductController : BaseController{public ActionResult Edit(int id){// 复用父类方法:校验登录if (!IsUserLogin())return RedirectToAction("Login", "Account");// 重写父类方法的场景(如果商品编辑需要特殊权限逻辑)// if (!CheckPermission("Product.Edit"))//     return Content("无权限");// 业务逻辑...return View();}}

【继承小结】

  • 核心价值:代码复用 + 功能扩展,父类存共性,子类存个性。
  • 关键语法:base关键字调用父类构造 / 方法,override重写父类虚方法。
  • 设计禁忌:避免多层继承(建议不超过 3 层),复杂场景用 “组合优于继承”(如 MVC 中Page类包含Server属性而非继承)。

1.4 多态:“同一行为,不同实现” 的灵活机制

多态允许不同对象对同一消息做出不同响应,通过抽象类或接口实现,核心是 “接口统一,实现各异”,是 MVC 中解耦的关键技术。
基础用法:抽象类 vs 接口(新手必懂)
多态有两种实现方式,二者适用场景截然不同,对比表如下:

维度抽象类(Abstract Class)接口(Interface)
核心关系IS-A(是什么,如 “狗是动物”)CAN-DO(能做什么,如 “能游泳”)
成员类型可包含字段、属性、具体方法、抽象方法仅含方法、属性、事件的签名(C# 8.0 后可加默认实现)
继承限制单继承(子类只能继承一个父类)多实现(类可实现多个接口)
状态管理可通过字段维护对象状态无字段,无法管理状态
版本兼容性新增非抽象方法不影响子类(兼容性高)新增成员强制子类实现(兼容性低)
MVC 场景Controller 基类(共享请求处理逻辑)IActionFilter(定义过滤器行为契约)

代码实战:抽象类与接口的协同使用

// 1. 抽象类:定义"动物"的本质(IS-A关系)
public abstract class Animal
{
public string Name { get; set; }
public abstract void MakeSound(); // 动物都会叫(共性行为)
}
// 2. 接口:定义"游泳"的能力(CAN-DO关系)
public interface ISwimable
{
// 接口方法:仅声明,无实现
void Swim();
}
// 3. 类:狗(是动物,能游泳)
public class Dog : Animal, ISwimable
{
public override void MakeSound()
{
Console.WriteLine($"{Name}:汪汪叫");
}
public void Swim()
{
Console.WriteLine($"{Name}用狗刨式游泳");
}
}
// 4. 类:鱼(是动物,能游泳)
public class Fish : Animal, ISwimable
{
public override void MakeSound()
{
Console.WriteLine($"{Name}:咕嘟叫");
}
public void Swim()
{
Console.WriteLine($"{Name}用鱼鳍划水游泳");
}
}
// 5. 类:人(不是动物,但能游泳)
public class Person : ISwimable
{
public string Name { get; set; }
public void Swim()
{
Console.WriteLine($"{Name}用自由泳游泳");
}
}
// 测试:多态的灵活调用
List<Animal> animals = new List<Animal>{new Dog { Name = "旺财" },new Fish { Name = "金鱼" }};// 同一方法调用,不同对象有不同响应foreach (var animal in animals){animal.MakeSound();}// 接口的多实现调用List<ISwimable> swimmers = new List<ISwimable>{new Dog { Name = "旺财" },new Fish { Name = "金鱼" },new Person { Name = "张三" }};foreach (var swimmer in swimmers){swimmer.Swim();}

MVC 实战:过滤器的多态应用
MVC 的过滤器通过接口实现多态,不同过滤器有不同实现但接口统一:

// 框架定义的接口(CAN-DO关系)
public interface IActionFilter
{
void OnActionExecuting(ActionExecutingContext context); // Action执行前
void OnActionExecuted(ActionExecutedContext context);  // Action执行后
}
// 日志过滤器(实现接口)
public class LogFilter : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
Console.WriteLine($"请求:{context.HttpContext.Request.Path}");
}
public void OnActionExecuted(ActionExecutedContext context)
{
Console.WriteLine($"响应状态:{context.HttpContext.Response.StatusCode}");
}
}
// 权限过滤器(实现接口)
public class AuthFilter : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
if (context.HttpContext.Session["UserId"] == null)
{
context.Result = new RedirectResult("/Account/Login");
}
}
public void OnActionExecuted(ActionExecutedContext context) { }
}
// Controller中自动调用(框架通过接口统一调度)
public class HomeController : Controller
{
// 过滤器通过特性绑定
[ServiceFilter(typeof(LogFilter))]
[ServiceFilter(typeof(AuthFilter))]
public IActionResult Index()
{
return View();
}
}

【多态小结】

  • 核心价值:解耦调用者与实现者,调用者只需依赖抽象(接口 / 抽象类),无需关心具体实现。
  • 选型原则:共性大于个性用抽象类(如动物类群),个性大于共性用接口(如游泳能力)。
  • MVC 精髓:通过接口(如IActionFilter)实现插件化扩展,新增功能无需修改原有框架代码。

二、OOP 设计原则:SOLID 原则实战解析

SOLID 原则是 OOP 设计的黄金准则,遵循这些原则可大幅提升代码的可维护性和扩展性,以下结合 C# 与 MVC 场景逐一解析。

2.1 单一职责原则(SRP)

定义: 一个类只负责一项职责,只有一个改变的原因。
反例: UserService同时处理用户管理和订单创建(两个职责)。正例: 拆分为用户服务和订单服务,各司其职:

// 1. 用户服务(仅负责用户相关逻辑)
public class UserService
{
public void CreateUser(User user)
{
// 校验用户数据、保存到数据库...
}
public User GetUserById(int id)
{
// 查询用户...
return new User();
}
}
// 2. 订单服务(仅负责订单相关逻辑)
public class OrderService
{
public void CreateOrder(Order order)
{
// 校验订单、关联用户...
}
}
// MVC Controller调用(职责清晰)
public class OrderController : Controller
{
private readonly UserService _userService;
private readonly OrderService _orderService;
public OrderController(UserService userService, OrderService orderService)
{
_userService = userService;
_orderService = orderService;
}
public IActionResult Create(OrderDto dto)
{
var user = _userService.GetUserById(dto.UserId);
if (user == null) return NotFound();
var order = new Order { UserId = dto.UserId, TotalAmount = dto.Amount };
_orderService.CreateOrder(order);
return Ok();
}
}

2.2 开放封闭原则(OCP)

定义: 对扩展开放,对修改封闭(新增功能通过扩展实现,不修改原有代码)。
实战案例: 订单计算折扣(新增折扣类型无需修改订单类):

// 1. 抽象折扣接口(稳定)
public interface IDiscountStrategy
{
decimal CalculateDiscount(decimal amount);
}
// 2. 具体折扣实现(可扩展)
public class VipDiscount : IDiscountStrategy
{
public decimal CalculateDiscount(decimal amount)
{
return amount * 0.8m; // VIP 8折
}
}
public class NewUserDiscount : IDiscountStrategy
{
public decimal CalculateDiscount(decimal amount)
{
return amount > 100 ? amount - 20 : amount; // 新用户满减
}
}
// 3. 订单类(无需修改)
public class Order
{
private readonly IDiscountStrategy _discount;
public Order(IDiscountStrategy discount)
{
_discount = discount;
}
public decimal GetFinalAmount(decimal amount)
{
return _discount.CalculateDiscount(amount); // 依赖抽象
}
}
// 调用:新增折扣类型只需加新类
var vipOrder = new Order(new VipDiscount());
var newUserOrder = new Order(new NewUserDiscount());

2.3 里氏替换原则(LSP)

定义: 子类可替换父类,且不改变程序的正确性(子类需遵循父类的行为契约)。
反例: 正方形继承矩形(破坏矩形 “宽高独立” 的契约);
正例: 通过接口实现,避免继承滥用:

// 抽象接口(定义行为契约)
public interface IShape
{
decimal GetArea();
}
// 矩形(符合契约)
public class Rectangle : IShape
{
public decimal Width { get; set; }
public decimal Height { get; set; }
public decimal GetArea()
{
return Width * Height;
}
}
// 正方形(符合契约,独立实现)
public class Square : IShape
{
public decimal Side { get; set; }
public decimal GetArea()
{
return Side * Side;
}
}
// 调用:子类可安全替换
List<IShape> shapes = new List<IShape> { new Rectangle(), new Square() };foreach (var shape in shapes){Console.WriteLine(shape.GetArea()); // 行为一致,结果正确}

2.4 接口隔离原则(ISP)

定义: 客户端不应被迫依赖不需要的接口,应将大接口拆分为小接口。
反例: IWorker接口包含Work和Eat方法,机器人无需Eat却必须实现;
正例: 拆分接口,按需实现:

// 拆分后的小接口
public interface IWorkable
{
void Work();
}
public interface IFeedable
{
void Eat();
}
// 人类(需工作和吃饭)
public class HumanWorker : IWorkable, IFeedable
{
public void Work() => Console.WriteLine("人类工作");
public void Eat() => Console.WriteLine("人类吃饭");
}
// 机器人(只需工作)
public class RobotWorker : IWorkable
{
public void Work() => Console.WriteLine("机器人工作");
// 无需实现Eat方法
}

2.5 依赖倒置原则(DIP)

定义: 高层模块不依赖低层模块,二者均依赖抽象;抽象不依赖细节,细节依赖抽象。
MVC 实战: 日志模块解耦(Controller 不依赖具体日志实现):

// 1. 抽象日志接口(高层与低层共同依赖)
public interface ILogger
{
void Log(string message);
}
// 2. 低层实现(细节依赖抽象)
public class FileLogger : ILogger
{
public void Log(string message)
{
File.AppendAllText("log.txt", message); // 写文件
}
}
public class DatabaseLogger : ILogger
{
public void Log(string message)
{
// 写数据库...
}
}
// 3. 高层模块(Controller依赖抽象)
public class UserController : Controller
{
private readonly ILogger _logger;
// 构造函数注入(依赖抽象而非具体)
public UserController(ILogger logger)
{
_logger = logger;
}
public IActionResult Login()
{
_logger.Log("用户登录请求"); // 调用抽象方法
return View();
}
}
// 配置依赖(切换实现只需改配置)
services.AddScoped<ILogger, FileLogger>();// services.AddScoped<ILogger, DatabaseLogger>();

【SOLID 原则小结】

  • SRP:一个类干一件事,避免 “万能类”;
  • OCP:通过抽象扩展功能,拒绝 “修改原有代码”;
  • LSP:子类不破坏父类契约,确保替换安全;
  • ISP:接口最小化,避免 “被迫实现无用方法”;
  • DIP:依赖抽象解耦,实现 “插件化替换”。

三、MVC 实战落地:OOP 综合应用案例

结合上述知识,我们构建一个 MVC 的 “订单管理系统” 核心模块,涵盖实体设计、业务逻辑、控制器调用全流程,代码可直接复制到项目中运行。

3.1 实体层设计(Model)

using System;
using System.ComponentModel.DataAnnotations;
// 1. 基类(继承复用)
public abstract class BaseEntity
{
[Key]
public int Id { get; set; }
public DateTime CreateTime { get; set; } = DateTime.Now;
}
// 2. 用户实体(封装)
public class User : BaseEntity
{
private string _password;
[Required]
[StringLength(20, MinimumLength = 3)]
public string Username { get; set; }
public string Email { get; set; }
public string PasswordHash => _password;
public void SetPassword(string password)
{
if (password.Length < 6)
throw new ValidationException("密码不少于6位");
_password = BCrypt.Net.BCrypt.HashPassword(password); // 正式加密
}
public bool VerifyPassword(string password)
{
return BCrypt.Net.BCrypt.Verify(password, _password);
}
}
// 3. 订单实体(多态)
public class Order : BaseEntity
{
public int UserId { get; set; }
public decimal TotalAmount { get; set; }
public string Status { get; set; } = "待支付";
// 虚方法:状态变更(允许子类重写)
public virtual void ChangeStatus(string newStatus)
{
Status = newStatus;
Console.WriteLine($"订单{Id}状态变更为:{newStatus}");
}
}
// 4. 退款订单(继承+多态)
public class RefundOrder : Order
{
public decimal RefundAmount { get; set; }
public string RefundReason { get; set; }
// 重写父类方法:添加退款特有逻辑
public override void ChangeStatus(string newStatus)
{
base.ChangeStatus(newStatus); // 调用父类逻辑
if (newStatus == "已退款")
{
Console.WriteLine($"订单{Id}已退款{RefundAmount}元,通知财务处理");
}
}
}

3.2 业务逻辑层(Service)

using System.Linq;
using Microsoft.EntityFrameworkCore;
// 1. 抽象服务接口(依赖倒置)
public interface IOrderService
{
Order CreateOrder(int userId, decimal amount);
bool ChangeOrderStatus(int orderId, string status);
}
// 2. 具体服务实现
public class OrderService : IOrderService
{
private readonly AppDbContext _dbContext;
private readonly ILogger _logger;
// 构造函数注入依赖
public OrderService(AppDbContext dbContext, ILogger logger)
{
_dbContext = dbContext;
_logger = logger;
}
public Order CreateOrder(int userId, decimal amount)
{
// 校验用户存在
var user = _dbContext.Users.Find(userId);
if (user == null)
throw new KeyNotFoundException("用户不存在");
// 创建订单
var order = new Order
{
UserId = userId,
TotalAmount = amount
};
_dbContext.Orders.Add(order);
_dbContext.SaveChanges();
_logger.Log($"创建订单:{order.Id},用户:{userId}");
return order;
}
public bool ChangeOrderStatus(int orderId, string status)
{
var order = _dbContext.Orders
.Include(o => o as RefundOrder) // 加载子类数据
.FirstOrDefault(o => o.Id == orderId);
if (order == null)
return false;
// 多态调用:自动执行对应子类的逻辑
order.ChangeStatus(status);
_dbContext.SaveChanges();
return true;
}
}

3.3 控制器层(Controller)

using Microsoft.AspNetCore.Mvc;
public class OrderController : BaseController
{
private readonly IOrderService _orderService;
public OrderController(IOrderService orderService)
{
_orderService = orderService;
}
// 创建订单(POST请求)
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(CreateOrderDto dto)
{
// 校验登录(复用BaseController方法)
if (!IsUserLogin())
return RedirectToAction("Login", "Account");
try
{
var order = _orderService.CreateOrder(GetCurrentUserId(), dto.Amount);
return Json(new { success = true, orderId = order.Id });
}
catch (Exception ex)
{
return Json(new { success = false, message = ex.Message });
}
}
// 变更订单状态
[HttpPost]
public IActionResult ChangeStatus(int orderId, string status)
{
if (!CheckPermission("Order.Manage"))
return Forbid();
var success = _orderService.ChangeOrderStatus(orderId, status);
return Json(new { success });
}
// 获取当前登录用户ID(BaseController方法)
private int GetCurrentUserId()
{
return Convert.ToInt32(Session["UserId"]);
}
}

3.4 数据库上下文(DbContext)

using Microsoft.EntityFrameworkCore;
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }// 实体集合public DbSet<User> Users { get; set; }public DbSet<Order> Orders { get; set; }// 配置继承关系(EF Core支持)protected override void OnModelCreating(ModelBuilder modelBuilder){// 订单的继承配置(TPH模式)modelBuilder.Entity<Order>().HasDiscriminator<string>("OrderType").HasValue<Order>("Normal").HasValue<RefundOrder>("Refund");}}

四、常见问题 FAQ(新手避坑指南)

常见问题解答与解决方案
抽象类能不能直接 new 实例?不能!抽象类是 “不完整的模板”,必须通过子类继承并实现抽象方法后,new 子类对象(如Animal a = new Dog())。
接口里能不能定义字段?不能!接口只能定义方法、属性、事件的签名,需通过实现类的字段维护状态(如ISwimable的实现类用字段存游泳速度)。
继承和组合选哪个更好?简单共性用继承(如 Controller 继承),复杂关系用组合(如Order包含User属性而非继承User),遵循 “组合优于继承” 原则。
多态调用时如何获取子类属性?用as或is转换类型(如var refundOrder = order as RefundOrder; if(refundOrder != null) { … })。
接口变更后如何兼容旧代码?新增接口而非修改原有接口(如ISwimableV2继承ISwimable),避免破坏所有实现类。

五、互动时间(3 重福利助力进阶)

本文整合了 OOP 基础、SOLID 原则、MVC 实战三大模块,代码已在.NET 6 环境下测试通过,可直接应用于实际项目。
1.基础巩固: 点赞 + 收藏本文,评论区留言 “OOP + 你最想练的案例”(如 “OOP + 购物车模块”),我会回复你的代码设计思路;
2.进阶资料: 评论区留言 “求 OOP 手册”,免费送《C# OOP 实战手册》(含 15 个 MVC 模块案例 + SOLID 原则检查表);
3.问题解答: 如果你在 “抽象类 vs 接口选型”" 多态调试 " 上卡壳,评论区描述你的问题,我会置顶详细解答(优先回复点赞前 3 的评论)。

下一篇预告

下一篇我们用 OOP + 设计模式,拆解 “MVC 中的依赖注入(DI)实战”—— 比如如何通过接口解耦 Service 与 Controller,如何设计可测试的业务逻辑,关注我的专栏,不错过核心技术干货!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/966458.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

tailwind自定义class问题小记

非常好的问题!您提到了两个关键点: 1. @layer components 是否合适? 是的,非常合适! pure-ipt 应该定义在 @layer components 中,因为:@layer base - 用于基础样式(如 *, body, html) @layer components - 用…

2025年主流开源AI智能体框架平台概览 - 实践

2025年主流开源AI智能体框架平台概览 - 实践2025-11-15 19:06 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: bl…

threading.local()的实例化机制

threading.local() 的实例化机制threading.local() 是全局实例化一次的:它在模块/类/函数级别(通常在 __init__ 或全局作用域)创建一个单一的 local 对象实例(类型为 _thread._local)。这个对象本身是共享的(所有…

Tarjan复建

塔尖踏践他荐太监肽键抬肩台站太真。写在前面: 我 \(C_aO\) 了全™的忘干净了于是步了鱼鱼的后尘开始切黄绿DP绿蓝 \(Tarjan\) 。 哎呀呀反正肝硬化不受人待见没人看就随便写写了。强连通分量: 这个没忘干净,当年为…

采用git进行项目管理

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Golang游戏开发笔记:地图索引系统实现

好家伙, 在游戏开发,尤其是后端服务的构建过程中,我们常常从一个简单的想法或原型开始。 代码直接、功能明确,一切看起来都很好。但随着项目复杂度的提升,最初的“简洁”设计往往会变成“僵化”的枷锁。0.需求分析…

20251115

依旧平凡的日常生活

网络爬虫:简单静/动态网页

爬虫实验*2 反思总结爬虫实验 实验一:静态网页 what to show? 实验一总流程 第一步:终端下载爬虫三件套第二步:创建文件。因为已经下载了vscode,这里用code进入,python运行。猜猜爬的是什么?第三步:爬虫中impo…

20232307 2024-2025-1 《网络与系统攻防技术》实验五实验报告

20232307 2024-2025-1 《网络与系统攻防技术》实验五实验报告 1. 实验内容 本周学习内容: 信息搜集:通过各种方式获取目标主机或网络的信息,属于攻击前的准备阶段 网络踩点:Google Hacking技术、Web信息搜集与挖掘…

EXECUTE IMMEDIATE语句分析

在 Oracle 的 PL/SQL 环境中,EXECUTE IMMEDIATE 通常需要包裹在 BEGIN...END 块中执行,因为它是 PL/SQL 的语法元素,不能直接在 SQL 命令行中单独执行(除非使用特定工具的简化模式)。 具体说明:在 PL/SQL 程序中…

产品更新与重构策略:创新与稳定的平衡之道 - 详解

产品更新与重构策略:创新与稳定的平衡之道 - 详解2025-11-15 18:47 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; displ…

MySQL MVCC实现原理

一、概述 1.1 MVCC的定义与价值 MVCC(Multi-Version Concurrency Control)是一种非锁定式并发控制技术,其核心目标是解决读写操作的相互阻塞问题。传统锁机制中,读操作加共享锁、写操作加排他锁,导致读写互斥;而…

算法第三次作业

算法第三次作业 1、按照动态规划法的求解步骤分析作业题目“数字三角形”: 1.1 根据最优子结构性质,列出递归方程式,说明方程式的定义、边界条件 a.递归方程式:c[j]=a[i][j]+max(c[j],c[j+1]) b.方程式的定义:数字…

完整教程:《简易制作 Linux Shell:详细分析原理、设计与实践》

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

计算机网络5 - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025年境外商务出差保险哪里有卖:TOP10平台专业解析

2025年境外商务出差保险哪里有卖:TOP10平台专业解析在当今全球化的商业环境中,境外商务出差已成为众多企业和商务人士的常态。然而,对于有境外商务出差需求的人来说,面临着诸多难题。“选品难(产品繁杂无从下手)…

2025年开除申诉靠谱机构推荐:专业学术申诉机构评测指南!

2025年开除申诉靠谱机构推荐:专业学术申诉机构评测指南!留学途中遭遇学术紧急情况?面临开除、停学或学术不端听证会,一家靠谱的申诉支持机构至关重要。本文基于教育部涉外监管认证信息、机构服务响应速度、申诉成功…

Day39(9)F:\硕士阶段\Java\课程代码\后端\web-ai-code\web-ai-project01\jdbc-demo+springboot-web-quickstart

DQL条件查询-- =================== DQL: 条件查询 ====================== -- 1. 查询 姓名 为 柴进 的员工 select * from emp where name = 柴进;-- 2. 查询 薪资小于等于5000 的员工信息 select * from emp where…

# Android Compose 实现 左滑删除

Android Compose 实现 左滑删除Android Compose 实现 左滑删除 直接看源码 private enum class CardState {Collapsed /* 收缩 */, Expanded /* 展开的 */ // 哈哈哈,还能学点英文 (: } @Composable private fun Pers…

win10pro sn

win10pro snVK7JG-NPHTM-C97JM-9MPGT-3V66T