面向对象

面向过程 VS 面向对象

面向过程

  • 以 过程 为中心 的编程思想,在编程时把 解决问题的 步骤 分解出来,使用函数实现这些步骤,再一步步按顺序调用函数,直至解决问题
  • 按照面向过程的思想,在解决问题时,各函数之间是为了问题服务
  • 面向过程思想偏向于我们做一件事的流程,首先做什么,其次做什么,最后做什么

特性

自顶向下、逐步求精、模块化

image.png

面向对象

  • 以 对象 为中心的编程思想,在编程时把要 解决的问题 抽象成 各个对象
  • 建立对象的目的 不是为了完成一个步骤,而是为了描叙某个对象在整个解决问题的步骤中的属性和行为
  • 按照面向对象的思想,是站在提出问题的主体的角度去解决问题,可将解决这一具体问题的步骤,抽象为解决这一类问题的方法,以后再遇到类似的问题,可以复用解决思路
  • 面向对象是按人们认识客观世界的系统思维方式,采用基于对象(实体)的概念建立模型,模拟客观世界分析、设计、实现软件的方法
  • 通过面向对象的理念,将计算机软件系统能与现实世界中的系统一一对应

特性

封装、继承、多态、抽象

image.png

举例

需求: 写一道 蛋炒饭 的程序

蛋炒饭 和 盖浇饭

蛋炒饭: 有一道工序是把 鸡蛋和 米饭混合一起炒
盖浇饭: 点什么菜,最后就把 这道菜 和 米饭混合一起炒

如果用 面向过程 的思想,写出了程序最后就是 一份 具体 的蛋炒饭
如果用 面向对象 的思想,可以根据 需要 写出 需要的 炒饭,可以是 蛋炒饭/红烧肉盖饭/青椒土豆盖浇饭

根据 面向过程的思想,就是只 做一道 蛋炒饭 的程序
根据 面向对象的思想,把 菜 和 饭 作为 对象 抽离 出来,根据需求 输入 相应 的菜 和饭,就能得到 对应 的 炒饭程序

面向对象编程的特征

面向对象编程的四项基本原则为:

  • 抽象:抽象是简化复杂系统的过程,将实体的相关特性和交互建模为类,以定义系统的抽象表示。抽象通过抽象类和接口来实现,抽象类定义了一些具体和一些抽象的方法,而接口定义了一组方法的契约,由实现类提供具体实现
  • 封装: 封装是将对象的状态(数据)和行为(方法)捆绑在一起,隐藏对象的内部状态和功能,通过使用访问修饰符,控制允许通过一组公共成员/函数进行访问
  • 继承:继承是一种机制,允许一个类(派生类)使用另一个类(基类)的属性和方法,同时继承也支持创建类的层次结构,通过在派生类中添加、修改或隐藏成员,实现对基类的扩展
  • 多态: 多态是一种通过同一接口(方法名)来表示不同实现的机制,多态通常通过方法的重写(override)和接口实现来实现

抽象

  • 抽象是通过隐藏不必要的细节,突出重点的特征,将实体抽象为类。
  • 抽象出来的类可以使用 abstract 关键字 来定义类

将计算图形面积 的共性 抽象成 类 Shape,使用具体实现类实现面积计算

// 抽象类
public abstract class Shape
{
    // 抽象方法,用于计算图形的面积
    public abstract double CalculateArea();
}
// Circle 是 具体的实现类 
public class Circle : Shape
{
    // 圆形的半径
    public double Radius { get; set; }

    // 实现 CalculateArea 方法: 计算圆型的面积
    public override double CalculateArea()
    {
        return Math.PI * Radius * Radius;
    }
}
// Rectangle 是 具体的实现类 
public class Rectangle : Shape
{
    // 矩形的长和宽
    public double Length { get; set; }
    public double Width { get; set; }

    // 实现 CalculateArea 方法: 计算矩形的面积
    public override double CalculateArea()
    {
        return Length * Width;
    }
}

封装

  • 封装是将数据和方法封装在同一个单元中
  • 通过定义公共接口(公共方法)来控制对数据的访问
  • 封装是为了防止外部直接访问数据,防止内部数据被随意的定义和修改,保障数据的安全性
image.png
public class Person
{
    // 封装的字段,私有字段只能在类内部访问
    private string name;
    private int age;

    // 封装的属性,提供对私有字段的访问和修改
    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    public int Age
    {
        get { return age; }
        set
        {
            // 对年龄进行一些验证
            if (value >= 0 && value <= 120)
            {
                age = value;
            }
            else
            {
                Console.WriteLine("Invalid age value");
            }
        }
    }

    // 公共方法,对外提供访问和操作封装字段的接口
    public void DisplayInfo()
    {
        Console.WriteLine($"Name: {Name}, Age: {Age}");
    }
}

class Program
{
    static void Main()
    {
        // 创建 Person 对象
        Person person1 = new Person();

        // 设置对象的属性值
        person1.Name = "John";
        // 设置 Age 的值, 但是 外界对于 Age 的一些验证并不知情
        person1.Age = 25;

        // 调用方法显示信息
        person1.DisplayInfo();
    }
}

继承

  • 基于某一个类进行扩展,使一个新类直接拥有基类的基本特征,而不需要重复去写,这就是继承的思想
  • C# 中,类只能继承一个类,一个子类只能有一个父类,一个父类可以有多个子类,若要实现多重继承,可以采用接口的形式
  • 在 C# 中,类默认继承自 System.Object 类,直接继承的是直接父类,即使没有显式指定某个类的基类,它仍然隐式地继承自 System.Object
  • C#中,使用 class 关键字来定义一个类,使用 :(冒号) 来表示继承关系
class Animal
{
    public void Eat()
    {
        Console.WriteLine("Animal is eating");
    }
}
// Mammal 类继承 Animal
class Mammal : Animal
{
    public void Sleep()
    {
        Console.WriteLine("Mammal is sleeping");
    }
}
// Dog 的直接父类是 Mammal,间接父类  Animal
class Dog : Mammal
{
    public void Bark()
    {
        Console.WriteLine("Dog is barking");
    }
}

多态

  • 多态是一种通过同一接口(方法名)来表示不同实现的机制
  • 多态性有两种主要形式:编译时多态性和运行时多态性
  • 编译时多态性(静态多态性)是编译时,通常与方法的重载(overloading)有关,同一个类中有多个方法具有相同的名称但不同的参数列表
  • 运行时多态性(动态多态性)是运行时,通常与方法的重写(overriding)有关,子类可以提供对基类方法的新实现
class Animal
{
    public virtual void MakeSound()
    {
        Console.WriteLine("Generic animal sound");
    }
}

class Dog : Animal
{
    // 重写
    public override void MakeSound()
    {
        Console.WriteLine("Woof! Woof!");
    }

    public void Gender(int x)
    {
        if(x==1)
         {
          Console.WriteLine("Gender: 男");
         }
         else if (x==2)
         {
           Console.WriteLine("Gender: 女");
         }
         else
         {
         Console.WriteLine("Gender: 不明确");
         }
    }
    // 重载
    public void Gender(string s)
    {
        Console.WriteLine("Gender: " + s);
    }

}

class Cat : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Meow!");
    }
}

class Program
{
    static void Main()
    {
        Animal animal = new Dog();
        animal.MakeSound();  // 运行时确定调用 Dog 类中的 MakeSound 方法
        animal.Gender(1);   // 编译时确定调用 Dog 类中的 Gender(int x)方法
        animal.Gender("男")  // 编译时确定调用 Dog 类中的 Gender(string x)方法
        animal = new Cat();
        animal.MakeSound();  // 运行时确定调用 Cat 类中的 MakeSound 方法
    }
}

方法的重载

方法的重载是指在同一个类中,可以定义多个具有相同名称但参数列表不同的方法

  • 重载的方法具有相同的方法名
  • 参数列表必须不同,包括参数的类型、个数或顺序
  • 返回类型可以相同也可以不同
class Calculator
{
    public int Add(int a, int b)
    {
        return a + b;
    }

    public double Add(double a, double b)
    {
        return a + b;
    }

    public string Add(string a, string b)
    {
        return a + b;
    }
}

方法的重写

方法的重写是指在派生类中重新实现(覆盖)基类中已有的方法

  • 重写的方法具有相同的方法签名(方法名、参数列表、返回类型),并且在基类中必须是虚拟(virtual)或抽象(abstract)的
  • 使用 override 关键字进行重写
class Shape
{
    public virtual void Draw()
    {
        Console.WriteLine("Drawing a shape");
    }
}

class Circle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("Drawing a circle");
    }
}

重写和重载的区别

方法名称

重载:方法名相同,参数列表不同
重写:方法名相同,参数列表相同

发生位置

重载:在同一个类中
重写:在派生类中

关键字

重载:使用相同的方法名,不需要额外的关键字
重写:使用 override 关键字

调用方式

重载:编译器根据调用时的参数类型、个数、顺序选择合适的方法
重写:运行时根据对象的实际类型选择调用的方法

用途

重载:提供更灵活的方法调用,可以根据不同的参数执行不同的逻辑
重写:实现多态,允许派生类提供特定于其类型的实现

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,188评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,464评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,562评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,893评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,917评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,708评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,430评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,342评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,801评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,976评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,115评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,804评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,458评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,008评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,135评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,365评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,055评论 2 355

推荐阅读更多精彩内容