C#面向对象编程基础 I

一.面向对象OOP

三大特点:数据的封装、继承、多态


二.继承

1.语法

class ChildClass : ParentClass


2.举例

public class Pet
    {
        public string Name;
        public void PrintName()
        {
            Console.WriteLine("Pet's name is" + Name);
        }
    }


    public class Dog:Pet
    {


    }
    public class Cat:Pet
    {


    }


    class Program
    {
        static void Main(string[] args)
        {
            Dog dog = new Dog();
            dog.Name = "Jack";
            dog.PrintName();
            Cat cat = new Cat();
            cat.Name = "Tom";
            cat.PrintName(); 
        }
    }


3.特殊的基类

Object类是所有类的共同基类,是唯一的非派生类。


4.规则

一个类只能继承一个父类。


三.隐藏方法

1.语法

屏蔽数据成员:在派生类中声明名称和类型相同的成员

屏蔽函数成员:在派生类中声明新的带有相同函数签名的成员

让编译器知道:可以添加new关键字,否则会有警告


2.举例

public class Pet
    {
        public string Name;
        public void PrintName()
        {
            Console.WriteLine("Pet's name is " + Name);
        }
    }


    public class Dog:Pet
    {
        new public void PrintName()
        {
            Console.WriteLine("宠物的名字是" + Name);
        }

    }
    public class Cat:Pet
    {


    }


    class Program
    {
        static void Main(string[] args)
        {
            Dog dog = new Dog();
            dog.Name = "Jack";
            dog.PrintName();
            Cat cat = new Cat();
            cat.Name = "Tom";
            cat.PrintName(); 
        }
    }


四.虚方法和多态

1.设计原则:依赖倒置原则

程序设计要依赖于抽象类(Pet),而不依赖于具体类(Dog)


2.基类的引用

当用基类类型的引用指向派生类时,仅仅能访问派生类中的基类部分

例如上面的例子,如果把dog的引用改为从基类Pet引用,那么之前在Dog中的隐藏方法就不能访问

......

class Program
    {
        static void Main(string[] args)
        {
            Pet dog = new Dog();
            dog.Name = "Jack";
            dog.PrintName();
            Cat cat = new Cat();
            cat.Name = "Tom";
            cat.PrintName(); 
        }
    }

运行结果中,dog的名字就是英文形式,而不是中文形式


3.统一提高效率

需要一个容器(比如数组)保存所有的基类(Pet)


4.子类具有差异


5.虚方法和多态的武器

可以解决既有统一的方法属性,又可以体现派生类的个性

声明为virtual的方法就是虚方法

基类的虚方法可以在派生类中用override进行重写



因为为了统一管理,一般都是用采用基类引用,所以再加上虚方法,就会达到兼顾统一又张扬个性的目的,而此时的情况更符合下图的描述


即,当pet调用speak方法时,由于是虚方法,所以程序会去找实际是dog派生类,所以就会调用dog的重写方法

但是,如果是dog直接调用speak方法,程序就直接调用speak方法


6.例如

public class Pet
    {
        public string Name;
        public void PrintName()
        {
            Console.WriteLine("Pet's name is " + Name);
        }
        virtual public void Speak()
        {
            Console.WriteLine(Name+" is speaking");
        }

    }


    public class Dog:Pet
    {
        new public void PrintName()
        {
            Console.WriteLine("宠物的名字是" + Name);
        }
        override public void Speak()
        {
            Console.WriteLine(Name + " is speaking "+"WoWo");
        }

    }
    public class Cat:Pet
    {
        override public void Speak()
        {
            Console.WriteLine(Name + " is speaking " + "MiMi");
        }

    }


    class Program
    {
        static void Main(string[] args)
        {
            Pet dog = new Dog();
            dog.Name = "Jack";
            dog.PrintName();
            dog.Speak();
            Cat cat = new Cat();
            cat.Name = "Tom";
            cat.PrintName();
            cat.Speak();
        }
    }


7.管理

例如

public class Pet
    {
        public string Name;
        public void PrintName()
        {
            Console.WriteLine("Pet's name is " + Name);
        }
        virtual public void Speak()
        {
            Console.WriteLine(Name+" is speaking");
        }
    }


    public class Dog:Pet
    {
        public Dog(string name)
        {
            Name = name;
        }

        new public void PrintName()
        {
            Console.WriteLine("宠物的名字是" + Name);
        }
        override public void Speak()
        {
            Console.WriteLine(Name + " is speaking "+"WoWo");
        }
    }
    public class Cat:Pet
    {
        public Cat(string name)
        {
            Name = name;
        }

        override public void Speak()
        {
            Console.WriteLine(Name + " is speaking " + "MiMi");
        }
    }


    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].Speak();
            }

           
        }
    }


8.关于虚方法的其它知识点

重写虚方法时,基类方法不能是private

static方法不能重写

方法、属性、索引器、事件,都可以用虚方法或重写


五.派生类和构造函数

1.构造函数就是初始化一个构造对象

在执行派生类的构造函数体之前,将会隐式或显示调用基类构造函数

如下图的调用顺序所示



2.调用基类构造函数



3.调用当前类的其它构造函数



六.抽象类和抽象方法

1.抽象方法语法

abstract  public void Func();

在基类不可以有函数体,只能在派生类中用override重写


2.当一个class含有一个抽象方法,就是抽象类

abstract class Pet

{

......

}

抽象类可以全是抽象成员,也可以全是普通成员(可以不声明abstract),也可以是它们的组合

抽象类的抽象成员在派生类中必须用override来重写


七.密闭类和密闭方法

1.用sealed关键字即为密闭类和密闭方法

不希望其他人继承修改某些类,或者不希望其他人重写某些方法,不希望派生出子类


2.如果一个基类方法不希望子类对其重写,不声明为virtual就行

如果是派生类方法不希望子类对其重写,同时是override重写,就可以用sealed机制


八.接口

1.接口是一种引用类型,指定一组函数成员但是不实现这些函数


2.语法

interface ICatchMice // 接口名称一般以I开头

{

  void CatchMice();  // 默认public,但不能加public

}


3.接口是用来被继承类实现

Cat : ICatchMice

{

  public void CatchMice() {......}

}


4.接口也是一种引用类型

Cat c = new Cat();

ICatchMice ic = (ICatchMice)c;

c.CatchMice ();  //通过对象调用

ic.CatchMice ();  //通过接口调用


5.接口可以实现一个类有多个接口

Cat : Pet, ICatchMice, IClimbTree

{

public void CatchRat(){...}

public void ClimbTree(){...}

...

}


6.例如

namespace PetShop
{
    interface ICatchMice
    {
        void CatchMice();
    }
    interface IClimbTree
    {
        void ClimbTree();
    }

    abstract public class Pet
    {
        public Pet(string name)
        {
            _name = name;
        }
        protected string _name;
        public void PringName()
        {
            Console.WriteLine("Pet's name is " + _name);
        }
        abstract public void Speak();
        virtual public void Move()
        {
        }
    }
    public class Dog:Pet
    {
        public Dog(string name):base(name)
        {
        }
        new public void PrintName()
        {
            Console.WriteLine("宠物的名字是" + _name);
        }
        sealed override public void Speak()
        {
            Console.WriteLine(_name + " is speaking:" + "WoWo");
        }
        public override void Move()
        {
        }
    }
    public class Labrador:Dog
    {
        public Labrador(string name):base(name)
        {
        }
    }
    public class Cat:Pet,ICatchMice,IClimbTree
    {
        public Cat(string name):base(name)
        {
        }
        public override void Speak()
        {
            Console.WriteLine(_name + " is speaking:" + "MiMi");
        }
        public void CatchMice()
        {
            Console.WriteLine("Catch mice");
        }
        public void ClimbTree()
        {
            Console.WriteLine("Climb tree");
        }

    }


    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].Speak();
            }
            Cat c = new Cat("Tom2");
            IClimbTree climb = (IClimbTree)c;
            c.ClimbTree();
            climb.ClimbTree();
            ICatchMice catchM = (ICatchMice)c;
            c.CatchMice();
            catchM.CatchMice();

        }
       
    }
}

运行结果



7.小贴士

接口并不是对一个类的补充描述,它是泛化的类,不是具体的事物,高级用法还可以是行为的组合。

比如,公司要招人,所签的合同就是接口。

屋主要打扫卫生,用猫或狗甚至人来抓屋子里的老鼠,这个抓老鼠就是接口。

学生要请家教来上课,上课就是接口,这个老师不满意可以换下一个老师。

人饿了,要用网站来订餐,这其中的饿了吃饭就是接口,必胜客不满意可以换麦当劳。


九.结构和类

1.不同点

结构是值类型(在栈中),类是引用类型(在堆中)

结构不支持继承,类支持继承

结构不能定义默认构造函数,编译器会定义


2.适用场合

结构:由于分配内存快,作用域结束即被删除,不需要垃圾回收,由于小型数据结构。

但传递过程中会复制,应该使用ref提高效率。


类:由于其他的需要继承体系的场合


3.例如

在PetShop中定义

struct fish

{

int weight;

int size;

int type;

}


之后在Cat中调用


4.小贴士

普通编程中很少用到结构,一般高手才会用结构。



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第1章 C#入门 1.1 NET框架和C#语言简介 1.1.1 NET框架简介 1.1.2 认识C≠语言 1.2 Visual Studio.NET集成开发环境简介 1.2.1 VS.NET起始页 1.2.2 VS.NET集成开发环境 1.2.3 窗口布局调整 1.3 第一个控制台应用程序 1.3.1 案例说明 1.3.2 案例实现步骤 1.3.3 代码及分析 1.3.4 相关知识及注意事项 1.4 我的第一个Windows窗体应用程序 1.4.1 案例说明 1.4.2 案例实现步骤 1.4.3 代码及分析 1.4.4 相关知识及注意事项 1.5 本章小结 1.6 习题 第2章 C#语法基础 2.1 C#语言的数据类型 2.1.1 案例说明 2.1.2 代码及分析 2.1.3 相关知识及滓意事项 2.2 C#语言的运算符和表达式 2.2.1 案例说明 2.2.2 代码及分析 2.2.3 相关知识及注意事项 2.3 本章小结 2.4 习题 第3章 C#程序结构 3.1 顺序与选择结构 3.1.1 案例说明 3.1.2 代码及分析 3.1.3 相关知识及注意事项 3.2 选择结构的窗体应用 3.2.1 案例说明 3.2.2 案例实现步骤 3.2.3 代码及分析 3.2.4 相关知识及注意事项 3.3 while、do.while循环 3.3.1 案例说明 3.3.2 代码及分析 3.3.3 相关知识及注意事项 3.4 for循环 3.4.1 案例说明 3.4.2 代码及分析 3.4.3 相关知识及注意事项 3.5 本章小结 3.6 习题 第4章 方法 4.1 方法的定义与调用 4.1.1 案例说明 4.1.2 代码及分析 4.1.3 相关知识及注意事项 4.2 方法的嵌套调用 4.2.1 案例说明 4.2.2 代码及分析 4.2.3 相关知识及注意事项   …… 第5章 类与对象 第6章 数组和索引器 第7章 继承 第8章 多态 第9章 接口 第10章 异常处理 第11章 委托和事件 第12章 文件操作 第13章 课程设计 参考文献

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值