C# 面向对象总结

C# 面向对象总结

Demo1: 使用C#查看和启动某进程

首先需要引入头文件:

using System.Diagnostics;

代码如下:

namespace _01进程
{
    class Program
    {
        static void Main(string[] args)
        {
            Process[] pro = Process.GetProcesses();
            foreach(var item in pro)
            {
                Console.WriteLine(item.ProcessName);
            }
            // 使用进程打开应用程序 
            Process.Start("notepad");
            Process.Start("mspaint");
            Process.Start("chrome", "www.baidu.com");

            // 使用进程打开文件

            // 首先封装要打开的文件
            ProcessStartInfo psi = new ProcessStartInfo(@"C:\Users\CY\Desktop\xxxxx.docx");
            // 创建进程对象
            Process process = new Process();
            process.StartInfo = psi;
            process.Start();
        }
    }
}

Demo2:使用简单的面向对象知识处理进程

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace _02打开文件练习
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("请输入要打开文件的所在路径");
            string filePath = Console.ReadLine();
            Console.WriteLine("请输入要打开文件的名字");
            string fileName = Console.ReadLine();

            // 通过简单工厂设计模式返回父类
            BaseFile bf = GetFile(filePath, fileName);
            if (bf != null)
            {
                bf.OpenFile();
            }

        }
        static BaseFile GetFile(string filePath, string fileName)
        {
            BaseFile bf = null;
            // 获得文件后缀名 
            string strExtension = Path.GetExtension(fileName);
            switch (strExtension)
            {
                case ".txt":
                    bf = new TxtFile(filePath, fileName);
                    break;
                case ".avi":
                    bf = new AviFile(filePath, fileName);
                    break;
                case ".mp4":
                    bf = new MP4File(filePath, fileName);
                    break;
            }
            return bf;
        }

    }
    // 由于不知道用户所选择的文件类型,因此需要一个表示文件的基类
    class BaseFile
    {
        // 能写在类中的内容:1.字段 2.属性 3.构造函数 4.函数 5.索引器
        
        // 构造函数
        public BaseFile(string filePath, string fileName)
        {
            this.FilePath = filePath;
            this.FileName = fileName;
        }
        private string _filePath;
        // 使用ctrl + r + e快捷键,封装字段,生成对应的属性
        public string FilePath
        {
            get
            {
                return _filePath;
            }

            set
            {
                _filePath = value;
            }
        }

        // 自动属性的快捷键:prop+tab+tab  
        public string FileName { get; set; }

        // 设计一个函数,用来打开指定的文件
        public void OpenFile()
        {
            ProcessStartInfo psi = new ProcessStartInfo(this.FilePath + "\\" + this.FileName);
            Process pro = new Process();
            pro.StartInfo = psi;
            pro.Start();
        }
    }


    // TXT文件类
    class TxtFile : BaseFile
    {
        // 由于子类默认调用父类的无参构造函数,而由于父类中实现了构造函数,因此父类中的默认无参构造函数失效
        // 这就需要子类重新实现构造函数
        // base(filePath, fileName)的作用:显示的调用父类的构造函数
        public TxtFile(string filePath, string fileName) : base(filePath, fileName)
        {

        }
    }
    // MP4文件类
    class MP4File : BaseFile
    {
        public MP4File(string filePath, string fileName) : base(filePath, fileName)
        {

        }
    }
    // AVI文件类
    class AviFile : BaseFile
    {
        public AviFile(string filePath, string fileName) : base(filePath, fileName)
        {

        }
    }
}

Demo3:面向对象练习

namespace _03面向对象练习
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }

    class Person
    {
        // 字段、属性、函数、构造函数

        // 字段:存储数据
        // 属性:用于保护字段
        // 函数:描述对象的行为
        // 构造函数:初始化对象,给对象的每个属性赋值

        string _name;

        public string Name
        {
            get
            {
                return _name;
            }

            set
            {
                _name = value;
            }
        }
        int _age;

        public int Age
        {
            get
            {
                return _age;
            }

            set
            {
                _age = value;
            }
        }

        public char Gender { get; set; }

        public Person(char gender)
        {
            if (gender != '男' && gender != '女')
            {
                gender = '男';
            }
            this.Gender = gender;
        }
    }
}

Demo4:三个关键字

C#中的三个关键字:
new
1. 创建对象
---在堆中开辟空间
---在开辟的堆空间中创建对象
---调用对象的构造函数
2. 隐藏父类的成员
this
1. 代表当前类的对象
2. 显式的调用自己的构造函数
base
1. 显式调用父类的构造函数
2. 调用父类的成员

namespace _04三个关键字
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }
    class Person
    {
        public void SayHello()
        {
            Console.WriteLine("我是人类");
        }
    }

    class Student : Person
    {
        // new的作用是显式告诉编译器SayHello已经覆盖了父类的SayHello函数,若不加new会有警告信息
        public new void SayHello()
        {
            Console.WriteLine("我是学生");
        }

        public Student GetStudent()
        {
            return this;
        }
        // base代表父类(不是父类对象)
        public void PersonSayHello()
        {
            base.SayHello();
        }
    }

    class Teacher
    {
        public string Name { get; set; }
        public int  Age { get; set; }
        public char Gender { get; set; }
        public int Chinese { get; set; }
        public int Math { get; set; }
        public int English { get; set; }

        // 构造函数
        public Teacher(string name, int age, char gender, int chinese, int math, int english)
        {
            this.Name = name;
            this.Age = age;
            this.Gender = gender;
            this.Chinese = chinese;
            this.Math = math;
            this.English = english;
        }
        // this:显式调用自己的构造函数
        public Teacher(string name, int age, char gender):this(name, age, gender, 0, 0, 0)
        {

        }
        public Teacher(string name, int chinese, int math,int english) : this(name, 0, '\0', chinese, math, english)
        {

        }
    }
}

Demo5:多态的实现

面向对象的三大特性:

  1. 封装:
    ---减少了大量的冗余代码
    ---封装功能,对外提供简单的接口
  2. 继承:
    ---减少了类中的冗余代码
    ---让类之间产生了关系,为多态打下基础
    继承的特性:
    ---单根性:一个子类只能有一个父类
    ---传递性:B继承A,C继承B,C可以访问A
    里氏转换:(子类和父类之间可以相互转化,这就是多态的基础)
    ---子类可以赋值给父类
    ---如果父类中装的是子类对象,则可以将这个父类转换为对应的子类对象
    ---关键字
    ---is:返回bool类型,指示是否可以做这个转化
    ---as:如果转化成功,则返回对象,否则返回null
    作用:我们可以将所有的子类都当作父类来看,针对父类进行编程,写出通用的代码,适应需求的不断改变。
  3. 多态:
    ---虚方法
    virtual override
    ---抽象类
    abstract override
    ---接口
    interface
namespace _05动物类继承
{
    class Program
    {
        static void Main(string[] args)
        {
            // 实现多态:声明父类去指向子类对象
            Animal[] a = { new Cat(), new Dog() };
            for(int i = 0; i < a.Length; i++)
            {
                a[i].Bark();
                a[i].Drink();
                a[i].Eat();
            }
        }
    }
    abstract class Animal
    {
        // 抽象成员只能存在于抽象类中
        public abstract void Bark();//父类没办法确定子类如何实现,因此不能写具体实现
        public void Eat()
        {
            Console.WriteLine("动物舔着吃");
        }
        public void Drink()
        {
            Console.WriteLine("动物舔着喝");
        }
    }
    class Cat : Animal
    {
        public override void Bark()
        {
            Console.WriteLine("猫咪喵喵叫");
        }
    }
    class Dog : Animal
    {
        public override void Bark()
        {
            Console.WriteLine("狗汪汪叫");
        }
    }
}

Demo6:里氏转换

namespace _06里氏转换
{
    class Program
    {
        static void Main(string[] args)
        {
            Person person = new Student();
            /*
            if (person is Teacher)
            {

            }
            */
            Student student = person as Student;// 将person转化为student对象
            if (student != null)
            {
                student.StudentSayHello();
            } else
            {
                Console.WriteLine("转换失败");
            }
        }
    }

    class Person
    {
        public void PersonSayHello()
        {
            Console.WriteLine("我是父类");
        }
    }
    class Student : Person
    {
        public void StudentSayHello()
        {
            Console.WriteLine("我是学生");
        }
    }
    class Teacher : Person
    {
        public void TeacherSayHello()
        {
            Console.WriteLine("我是老师");
        }
    }
}

Demo7:virtual和override

若不加virtual和override关键字时

namespace _07虚方法
{
    class Program
    {
        static void Main(string[] args)
        {
            BaseClass baseClass = new BaseClass();
            Derived derived = new Derived();


            baseClass.PrintMethod();//输出base
            derived.PrintMethod();//输出devired
            baseClass = new Derived();
            baseClass.PrintMethod();//输出base
        }
    }
    class BaseClass
    {
        public void PrintMethod()
        {
            Console.WriteLine("base");
        }
    }
    class Derived : BaseClass
    {
        public void PrintMethod()//此处有警告,因为覆盖了父类的方法,并且没有显式加new关键字
        {
            Console.WriteLine("derived");
        }
    }
}

上述没有使用virtual和override的重写实际上起到了隐藏父类方法的作用

2.使用virtual和override的重写

namespace _07虚方法
{
    class Program
    {
        static void Main(string[] args)
        {
            BaseClass baseClass = new BaseClass();
            Derived derived = new Derived();


            baseClass.PrintMethod();//输出base
            derived.PrintMethod();//输出devired
            baseClass = new Derived();
            baseClass.PrintMethod();//输出devired
        }
    }
    class BaseClass
    {
        public virtual void PrintMethod()
        {
            Console.WriteLine("base");
        }
    }
    class Derived : BaseClass
    {
        public override void PrintMethod()
        {
            Console.WriteLine("derived");
        }
    }
}

解释如下:

BaseClass baseClass = new Derived();

上述语句,BaseClass叫做声名类,Derived叫做实例类
编译器具体的检查流程如下:
1.当调用函数时,系统直接检查声明类,查看所调用函数是否是虚函数
2.如果不是,直接执行该函数。若是virtual函数,转去检查实例类
3.在实例类中,若有override的函数,则执行,若没有,则依次上溯,对父类进行检查,直到找到第一个override了此函数的父类,然后执行

因此,若Derived类中没有override,则在BaseClass中执行同名函数

Demo8:抽象类

抽象类知识点:

  1. 抽象成员必须标记为abstract,并且不能有具体实现
  2. 抽象成员必须在抽象类中
  3. 抽象类不能被实例化
  4. 子类继承抽象类后,必须把父类中的所有抽象成员重写(若子类也是抽象类,则不用)
  5. 抽象成员的访问修饰符不能是private
  6. 抽象类中可以包含实例成员,并且抽象类中的实例成员可以不被子类实现
  7. 抽象类有构造函数,虽然不能被实例化
  8. 如果父类的抽象方法中有参数,则继承这个父类的子类在重写父类的方法时必须传入对应参数,返回值同理
若父类中的方法有默认的实现,并且父类需要被实例化,可以考虑将父类定义成一个普通类,用虚方法来实现多态
若父类中的方法没有默认实现,父类也不需要被实例化,则可以定义为抽象类
namespace _08抽象类练习
{
    class Program
    {
        static void Main(string[] args)
        {
            
        }
    }
    // 抽象类
    abstract class MobileStorage
    {
        public abstract void Read();
        public abstract void Write();

    }
    class Phone : MobileStorage
    {
        public override void Read()
        {
            Console.WriteLine("手机在读取数据");
        }
        public override void Write()
        {
            Console.WriteLine("手机在写入数据");
        }
    }

    class MP3 : MobileStorage
    {
        public override void Read()
        {
            Console.WriteLine("MP3在读取数据");
        }

        public override void Write()
        {
            Console.WriteLine("MP3在写入数据");
        }
        public void PlayMusic()
        {
            Console.WriteLine("MP3在播放音乐");
        }
    }

    class Computer
    {
        public MobileStorage MS
        {
            get;
            set;
        }
        public void ComputerRead()
        {
            this.MS.Read();
        }
        public void ComputerWrite()
        {
            this.MS.Write();
        }
    }
}

Demo9:接口的使用

接口知识点:

  1. 接口更多的表示一种规范,一种能力,功能要单一
  2. 一个类继承了一个接口,就必须实现这个接口的所有成员
  3. 接口不能被实例化
  4. 接口中的成员不能加访问修饰符,默认为public,不能修改
  5. 接口中的成员不能有任何实现
  6. 接口中只能有方法、属性、索引器、事件,不能有字段和构造函数
  7. 接口之间可以继承
  8. 实现接口的子类必须实现该接口的所有成员
  9. 一个类可以同时继承一个类并实现多个接口,如果一个子类同时继承了父类A,并实现了接口IA,则语法上A必须写在IA前面
  10. 当一个抽象类实现接口时,需要子类去实现接口
namespace _09接口的使用
{
    class Program
    {
        static void Main(string[] args)
        {
            // 实现多态
            IEat[] eaters = { new Student(), new Teacher() };
            for (int i = 0; i != eaters.Length; i++)
            {
                eaters[i].Eat();
            }
            
        }
    }

    class Person
    {
        public void PersonSayHello()
        {
            Console.WriteLine("Person:Hello!");
        }
    }

    interface IEat
    {
        void Eat();
    }

    class Student : Person, IEat
    {
        public void Eat()
        {
            Console.WriteLine("Student:I Can Eat");
        }
    }
    class Teacher: Person, IEat
    {
        public void Eat()
        {
            Console.WriteLine("Teacher:I Can Eat too");
        }
    }
}

Demo10:显示实现接口

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

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,560评论 18 399
  • 继承是面向对象的三大特性之一。 1.继承 1.1概念:一个类从其他类派生时,派生类隐式获得基类除构造函数和析构函数...
    X江阅读 207评论 0 0
  • 一:java概述:1,JDK:Java Development Kit,java的开发和运行环境,java的开发工...
    ZaneInTheSun阅读 2,627评论 0 11
  • 原文链接:https://github.com/EasyKotlin 在前面的章节中,我们学习了Kotlin的语言...
    JackChen1024阅读 841评论 0 3
  • 朋友们 累了,能不叫苦吗 伤了,能不流泪吗 心碎了,能拾起来吗 就像天空 没有星星,可以不顾世人有无光 就像起风了...
    金书js阅读 230评论 0 2