C#面向对象编程基础 I

xiaoxiao2021-02-28  77

一.面向对象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.小贴士

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

转载请注明原文地址: https://www.6miu.com/read-60249.html

最新回复(0)