04_C#学习_面向对象

2019-03-07

面向对象编程

特点:封装,继承,多态(子类)
优点:易维护,易扩展,易开发
—— 与面向过程编程相对。

1. 继承

为什么要继承:不用写重复的代码
怎么实现继承:一个类派生于另一个基类,它拥有该基础类型的所有成员字段和函数。
理解:直接将基类里面的代码copy到派生类中
规则:单继承,只能继承一个父类。


语法:

class ChildClass : ParentClass
{...
}

2. 隐藏方法

派生类希望在从基类继承来的方法中,进行独特性的改变。

  • 不能删除基类中任何方法,但可以使用相同名称的方法来屏蔽基类方法。
  • 语法细节:在派生类中声明相同名称和类型的成员;并在前面添加new关键词
class Pet
    {
        public string Name;
        public void PrintName()
        {
            Console.WriteLine("Pet's name is:" + Name);
        }
    }
 class Dog:Pet
    {//new 方法;在派生类中进行了方法修改
        new public void PrintName()
        {
            Console.WriteLine("狗的名字是:" + Name);
        }
    }
//在Dog类实例化对象下,执行new方法
//在Pet类实例化对象,执行基类原来的方法

3. 虚方法和多态:virtual,override

  1. 设计原则:尽量依赖抽象类(Pet),而不依赖于具体类(Dog)

  2. 基类的引用:基类的引用,并指向派生类

Pet dog = new Dog();

dog能访问的内容是:Pet基类中正常部分+Pet基类中的虚方法在Dog派生类中override的重写对象。

  1. 提高效率:首先,我们希望能进行统一的管理,通过一个容器(数组)能保存所有对象(Dog,Cat),但是这些对象必须是同类型的。 所以,通过一个基类类型的数组储存所有对象,并通过虚方法和多态实现个性化。
Pet[] pets = new Pet[] { new Dog("Jack"), new Cat("Tom") };
  1. 虚方法和多态
    虚方法:声明为virtual的方法是虚方法。基类的虚方法可以在派生类中使用override进行重写
    多态:指向派生类的基类引用,调用虚函数时候,会调用派生类中的同名重写函数,便是多态。
//基类Pet
  class Pet{
        public string Name;
        public void PrintName()
        {
            Console.WriteLine("Pet's name is:" + Name);
        }
        virtual public void Speak()
        {
            Console.WriteLine(Name+" is speaking");
        }
    }
//子类Dog
 class Dog:Pet{
        public Dog(string name)
        {
            this.Name = name;
        }

        public override void Speak()
        {
            Console.WriteLine(Name + " is speaking:"+"wangwang");
        }
    }
//子类Cat
 class Cat:Pet {
        public Cat(string name)
        {
            Name = name;
        }
        public override void Speak()
        {
            Console.WriteLine(Name + " is speaking:"+"miaomiao");
        }
    }
//主程序
    class Program{
        static void Main(string[] args){
            Pet[] pets = new Pet[] { new Dog("Jack"), new Cat("Tom") };
            for (int i = 0; i < pets.Length; i++)
            {
                pets[i].PrintName();
                pets[i].Speak();
            }
        }
    }

4. 派生类及构造函数

  1. 调用顺序


  2. 指向派生类的基类引用,要用派生类的构造函数,派生类的构造函数通过public Dog(string name):base(name)引用调用基类的构造函数。

   class Pet{
        public Pet(string name)
        {
            _name = name;
        }
}
   class Dog:Pet{
        public Dog(string name):base(name)
        {
        }
}
  class Cat:Pet{
        public Cat(string name):base(name)
        {
        }
}

 Pet[] pets = new Pet[] { new Dog("Jack"), new Cat("Tom") };

5. 抽象方法和类 abstract

  • abstract比virtual更加抽象,无函数体,必须要在子类进行重写

  • 有抽象方法的一定是抽象类,需要声明为abstract class Pet

  • 抽象类的目的:被继承。

  • 抽象类不能实例化,用abstract修饰

  • 抽象类可以包含抽象成员和普通成员,抽象对象在派生类中需要用override重写

abstract class Pet
    {
        public Pet(string name)
        {
            _name = name;
        }
        abstract public void Speak();
 }

6. 密闭类和密闭方法

  • 关键词:sealed
  • 为什么要密闭:不希望原来的类或者方法被其他人修改或重写(比如:string类是sealed类)
  • 密闭方法:如果一个基类方法不希望子类对其重写,就可以不声明virual。如果是派生类方法不希望被子类重写,同时又是override重写,就可以使用sealed机制
sealed public override void Speak()

7. 接口

接口笔记链接

  • 接口是什么:接口是指一组函数成员,而不实现他们的引用类型。(比抽象类还抽象,像没有普通函数的抽象类)
interface ICatchMice
{
  void CatchMice(); //里面是空方法
}
-- 不能加任何访问修饰符,但默认是public
  • 作用:用来被别的类实现,被继承
//定义接口
interface ICatchMice
    {
        void CatchMice();
    }
interface IClimbTree
    {
        void ClimbTree();
    }
//Cat类继承接口
class Cat:Pet,ICatchMice,IClimbTree
    {
        public Cat(string name):base(name)
        {
        }
        public void CatchMice()
        {
            Console.WriteLine("Catch Mice");
        }
        public void ClimbTree()
        {
            Console.WriteLine("Climb Tree");
        }
    }
 class Program
    {
        static void Main(string[] args)
        {
            Cat cat = new Cat("Tom2");
            cat.CatchMice(); //用对象调用方法
            IClimbTree climb = (IClimbTree)cat;
            climb.ClimbTree(); //用接口调用方法
            ICatchMice catchMice = (ICatchMice)cat;
            catchMice.CatchMice();
        }
    }

8. 结构与类

  1. 不同点
  • 结构是值类型(在栈中),类是引用类型(在堆中)
  • 结构不支持继承但可以实现接口,类支持继承
  • 结构不能定义默认构造函数,编译器会定义
  1. 适用类型
  • 结构:由于分配内存块,作用域结束即被删除,不需要垃圾回收,用于小型结构类型。但传递过程中会复制,应该适用ref引用提高效率

  • 类:用于需要继承体系的场合

9. 静态成员

  • 什么是静态成员:标识为stactic的字段,方法,属性,构造函数,时间,就是静态成员。static int Num

  • 重点:静态成员被类的所有实例共享,所有实例都访问统一内存位置

  • 如何访问静态成员:直接通过类名访问 Dog.Num+=1;

  • 静态函数:独立于任何实例,没有实例也可以访问。静态函数不能访问实例成员,仅能访问静态成员

  • 静态构造函数:静态构造函数用于初始化静态字段;在引用静态成员之前和创建任何实例之前调用;与类同名,使用static,无参数,无访问修饰符 static Dog()

 class Dog:Pet
    {
        static int Num;
        static Dog()  //静态构造函数初始化Num,仅能访问静态成员
        {
            Num = 0;
        }
        public Dog(string name):base(name)
        {
            ++Num;
        }
        static public void ShowNum()
        {
            Console.WriteLine("Dog's number is " + Num);
        }
    }
 class Program
    {
        static void Main(string[] args)
        {
           Dog dog = new Dog("Tim");
           Dog.ShowNum();  //通过类直接调用静态方法
         }
     }

10. 静态类

  • 静态类:只包含静态的方法和属性,并标识为static。

  • 静态类不能创建实例,不能被继承。可以为静态类定义一个静态构造函数。

  • 作用:主要用于基础类库(如数学库)和扩展方法。

  • 扩展方法:如有源代码,直接添加一个新方法;如果不能修改但也不是密闭类,可以派生子类扩展;如果以上条件都不满足,可使用静态类扩展方法

  • 扩展方法的第一个参数类型,必须是this+类名。之后在实例对象中可以像自己的方法一样能直接调用静态类的方法

static class PetGuide
    {
        public static void HowToFeedDog(this Dog dog)
        {
            ...  
            Console.WriteLine("Play a vedio about how to feed a dog");
        }
    }
class Program
    {
        static void Main(string[] args)
        {
            Dog dog = new Dog("Tim");
            dog.HowToFeedDog();  //像自己的方法一样直接调用静态类的方法
         }
    }

11. 装箱和拆箱

  • 装箱:值类型转换为引用类型,是一种隐式转换
  • 为什么要装箱:进行统一的操作和统一的存储
int i = 3;
object oi = null;
oi = i;
  • 拆箱:是将装箱后的对象转换为值类型的过程,是一种显示转换。
int i = 3;
object oi = i;
int j = (int) oi;

12. 自定义转换

  • 什么是自定义转换:为自己的结构或者类定义显示和隐式转换
  • 为什么:为了让结构或者类可以变成一个预期相关的类型,并且这种转换更简单
  • 隐式转换语法:
 static public implicit operator Cat(Dog dog)
        {
            return new Cat(dog._name);
        }
  • 显式转换语法:
static public explicit operator Dog(Cat cat)
        {
            return new Dog(cat._name);
        }
  • 应用:
   Dog dog = new Dog("Jack");
    dog.Speak();
    Cat cat = dog;
    cat.Speak();
    Dog dog2 = (Dog)cat;
    dog2.Speak();

13. 重载运算符

  • 含义:利用现有的某种运算符,针对自定义类或结构,定义某种运算操作(公狗+母狗=新生狗狗)

  • 意义:利用现有运算符,简化操作,具有一定相关性

  • 运算符:


  • 不能创造新运算符,不能改变运算符语法,不能重定义运算符处理预定义类型,不能改变运算符的优先级和结合性。

  • 语法:public static Dog operator +(Dog male,Dog female)

class Dog:Pet
    {...
 static public Dog operator +(Dog dog1,Dog dog2)
        {
            if ((dog1.Sex == (Sex)0 && dog2.Sex == (Sex)1) || (dog1.Sex == (Sex)1 &&dog2.Sex == (Sex)0) )
            {
                return new Dog(dog1._name + dog2._name, Sex.female);
            }
            else
            {
                Console.WriteLine("Can't bath new baby");
                return null;
            }
        }
    }

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

推荐阅读更多精彩内容

  • 面向对象介绍 范式编程 编程是程序员用 特定的语法+数据结构+算法 组成的代码来告诉计算机如何执行任务的过程。 一...
    drfung阅读 1,913评论 0 1
  • C++类和对象 C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计。类是 C++ 的核心...
    863cda997e42阅读 647评论 0 4
  • 访问限定符 类的属性和方法在类外访问时有不同的限定词来修饰,C++中提供了public/protect/priva...
    helloworldzlg阅读 164评论 0 0
  • 如今各种好吃的琳琅满目,各种好玩的地方多的数不胜数,但小时候充满仪式感的过大年,却随着岁月的流逝越来越清晰的刻在人...
    笑笑8阅读 304评论 0 10
  • 每一年的秋天,大概十一月多,我总会去一趟鼓浪屿。说来实在惭愧,在厦门读大学那么久,现在已经是快要毕业,竟然很少认认...
    赤尼巫人阅读 477评论 0 0