数据结构与算法:03 C#面向对象设计 I
03 C#面向对象设计 I
知识结构:
1、类与对象
- 类:用高级程序语言实现的一个ADT描述。
- 对象:通过类声明的变量。
2、封装
2.1 什么是封装
把类的内部隐藏起来以防止外部看到内部的实现过程。
2.2 怎样封装
- 通过限制修饰符
private
、protected
、public
、internal
来实现。 - 对类中的数据(Data)和操作(Operation)的限制修饰符:
private
:只允许类的内部访问(默认)。protected
:只允许类的内部和子类访问。public
:类的内部与外部都可以访问。internal
:在同一程序集内部访问,相当于public
。
- 对类的限制修饰符:
public
:都可以使用。internal
:在同一程序集内部使用(默认)。
注:internal
修饰的类,方法或属性,只要是在同一个程序集中的其它类都可以访问,如果二者不在同一命名空间,只要使用using
引用上相应的命名空间即可,这里,从另外一个方面也间接看出命名空间并不是界定访问级别的,而是保证全局的类唯一性的。
参考图文:
- 技术图文:如何理解C#的internal限定修饰符?
2.3 怎样表示
- 类图(Class Diagram)
- -:
private
- +:
public
- #:
protected
- -:
例1:根据下列类图实现Animal类型。
public class Animal
{public int Age;public double Weight;public void Eat(){Console.WriteLine("Animal Eat.");}public void Sleep(){Console.WriteLine("Animal Sleep.");}
}class Program
{static void Main(string[] args){Animal al = new Animal();al.Eat();// Animal Eat.al.Sleep();// Animal Sleep.}
}
3、继承
3.1 什么是继承
子类拥有父类某些Data和Operation的过程。
3.2 怎样继承
public class Child : Parent
{ //…
}
Child
:子类(派生类),Parent
:父类(基类)- 在类的声明中,利用“:”表示继承。
C# 只支持单继承,但可以定义一个不允许其它类继承的类。
public sealed class Name
{//...
}
- 利用
sealed
关键字可防止所声明的类被继承。
子类与父类中数据与操作的继承关系:
- 父类
public
protected
private
internal
- 子类
public
protected
无法继承internal
3.3 子类怎样访问父类成员
利用base
关键字。
例2:子类访问父类且父类构造函数不带参数。
public class Parent
{private int _data1; // 只能被类的内部访问protected int Data2; // 能被子类访问和继承public int Data3; // 能被子类访问和继承
}public class Child : Parent
{public Child(){base.Data2 = 2;base.Data3 = 3;}
}class Program
{static void Main(string[] args){Child cld = new Child();Console.WriteLine(cld.Data3); // 3}
}
例3:子类访问父类且父类构造函数带参数。
public class Parent
{private int _data1; // 只能被类的内部访问protected int Data2; // 能被子类访问和继承public int Data3; // 能被子类访问和继承public Parent(int dt1, int dt2, int dt3){_data1 = dt1;Data2 = dt2;Data3 = dt3;}
}public class Child : Parent
{public Child() : base(0, 2, 3){;}
}class Program
{static void Main(string[] args){Child cld = new Child();Console.WriteLine(cld.Data3);// 3}
}
3.4 怎样表示
- 通过类图来表示
例4:根据类图实现程序代码,注意类之间的继承关系。
public class Animal
{public int Age;public double Weight;public void Eat(){Console.WriteLine("Animal Eat.");}public void Sleep(){Console.WriteLine("Animal Sleep.");}
}public class Bird : Animal
{public void Fly(){Console.WriteLine("Bird Fly.");}
}public class Dog : Animal
{public void Run(){Console.WriteLine("Dog Run.");}
}public class Fish : Animal
{public void Swim(){Console.WriteLine("Fish Swim.");}
}class Program
{static void Main(string[] args){Dog dog = new Dog();dog.Run(); //Dog Run.Bird bird = new Bird();bird.Fly(); //Bird Fly.Fish fish = new Fish();fish.Swim(); //Fish Swim.}
}
3.5 实例化
为对象分配存储空间的过程。
例5:类的实例化。
public class Animal
{public int Age;public double Weight;public void Eat(){Console.WriteLine("Animal Eat.");}public void Sleep(){Console.WriteLine("Animal Sleep.");}
}public class Dog : Animal
{public void Run(){Console.WriteLine("Dog Run.");}
}class Program
{static void Main(string[] args){Animal al = new Animal(); // 实例化Animalal.Eat(); // Animal Eat.al.Sleep(); // Animal Sleep.Dog dg = new Dog(); // 实例化Dogdg.Age = 2;dg.Weight = 4.5;Console.WriteLine("Dog Infor: Age:{0},Weight:{1}",dg.Age, dg.Weight);// Dog Infor: Age:2, Weight:4.5dg.Sleep(); // Animal Sleep.dg.Eat(); // Animal Eat.dg.Run(); // Dog Run.}
}
例6:子类与父类有重名方法。
public class Animal
{public int Age;public double Weight;public void Eat(){Console.WriteLine("Animal Eat.");}public void Sleep(){Console.WriteLine("Animal Sleep.");}
}public class Dog : Animal
{public void Eat(){Console.WriteLine("Dog Eat.");}public void Sleep(){Console.WriteLine("Dog Sleep.");}public void Run(){Console.WriteLine("Dog Run.");}
}
class Program
{static void Main(string[] args){Animal al = new Dog(); // 子类可以实例化父类al.Eat(); // Animal Eat.(重名方法存在问题)al.Sleep(); // Animal Sleep.Dog dg = al as Dog; //强制类型转换或Dog dg = (Dog)al;dg.Eat(); // Dog Eat.dg.Sleep(); // Dog Sleep.dg.Run(); // Dog Run.}
}
注意:
Animal al = new Dog();
(正确)Dog dg = new Animal();
(错误)
子类可以实例化父类,而父类不可以实例化子类,即:Dog
一定是Animal
,而Animal
不一定是Dog
。
Animal al = new Dog();
Dog dg = al;
(错误)需要强制类型转换。Dog dg = al as Dog;
(正确)若al
不是Dog
类型,返回null。Dog dg = (Dog)al;
(正确)若al
不是Dog
类型,系统会抛出异常。
4、多态
4.1 什么是多态
相同的操作(Operation),对于不同的对象,可以有不同的解释,产生不同的执行结果。
4.2 多态的分类
- 运行时多态:在运行时决定执行哪个类的哪个方法。(override覆写)
- 编译时多态:在编译时决定执行类中的哪个方法。(overload重载)
4.3 多态的实现
运行时多态:
- 在父类中定义并实现虚方法(virtual)
- 在子类中覆写(override)该虚方法。
- 虚方法必须有方法体
- 覆写虚方法,要求方法名,形参,返回值类型必须相同。
例7:实现运行时多态的代码
public class Animal
{public int Age;public double Weight;public virtual void Eat(){Console.WriteLine("Animal Eat.");}public virtual void Sleep(){Console.WriteLine("Animal Sleep.");}
}public class Dog : Animal
{public override void Eat(){Console.WriteLine("Dog Eat.");}public override void Sleep(){Console.WriteLine("Dog Sleep.");}public virtual void Run(){Console.WriteLine("Dog Run.");}
}class Program
{static void Main(string[] args){Animal al = new Dog();//在执行时,通过判断al的类型来决定执行哪个类中的哪个方法;al.Eat(); // Dog Eat.al.Sleep(); // Dog Sleep.}
}
编译时多态:
- 类中定义的方法或操作符可能有不同的版本。
- 操作符重载:
operator
关键字 - public static 类型 operator 运算符(形参列表){ … }
- 方法重载:必须有相同的方法名、必须有不同的参数列表、可以有相同的返回值类型
例8:通过类图实现编译时多态的代码
public class Complex
{public int A;public int B;public Complex(int a, int b){this.A = a; //this表示在内存中Complex对象this.B = b;}public static Complex operator +(Complex c1, Complex c2){return new Complex(c1.A + c2.A, c1.B + c2.B);}public override string ToString(){return string.Format("{0}+{1}i", A, B);}
}public class Math
{public int Add(int x, int y){return x + y;}public double Add(double x, double y){return x + y;}public Complex Add(Complex x, Complex y){return x + y;}
}class Program
{static void Main(string[] args){Complex c1 = new Complex(1, 2);Complex c2 = new Complex(3, 4);Complex c3 = c1 + c2;Console.WriteLine("C1={0}", c1); // C1=1+2iConsole.WriteLine("C2={0}", c2); // C2=3+4iConsole.WriteLine("C3={0}", c3); // C3=4+6iMath mth = new Math();Complex c4 = mth.Add(c2, c3);//在编译时,根据参数列表决定执行哪个类中的哪个方法;Console.WriteLine("C4={0}", c4); // C4=7+10i}
}
总结:override
和overload
4.4 抽象方法与抽象类
- 抽象方法:可以看成没有实现体的虚方法(
abstract
),即只有方法的声明,需要在子类中覆写(override
)该方法。 - 抽象类:含有抽象方法的类。抽象类不可以直接实例化对象。
例9:根据类图实现代码
public abstract class Animal
{public int Age;public double Weight;public abstract void Eat();public abstract void Sleep();
}public class Dog : Animal
{public override void Eat(){Console.WriteLine("Dog Eat.");}public override void Sleep(){Console.WriteLine("Dog Sleep.");}public void Run(){Console.WriteLine("Dog Run.");}
}class Program
{static void Main(string[] args){Animal al = new Dog();al.Eat(); // Dog Eat.al.Sleep(); // Dog Sleep.((Dog)al).Run(); // Dog Run.}
}
注意:
al.Run();
(错误)((Dog)al).Run();
(正确)
抽象类中并没有Run方法,如果使用需要强制类型转换。
Animal al = new Animal ();
(错误)
抽象类不可以直接实例化对象,系统会抛出异常。
总结:抽象方法和虚方法
例10:饲养系统
某饲养员(Raiser)在目前状态下需要饲养三种动物:狗(Dog)、鸟(Bird)和鱼(Fish),该三种动物只需要让其睡觉(Sleep)和吃饭(Eat)即可。
请设计该饲养系统,要求满足软件设计的“开闭原则”。
方案一:
public class Bird
{public void Eat(){Console.WriteLine("Bird Eat.");}public void Sleep(){Console.WriteLine("Bird Sleep.");}public void Fly(){Console.WriteLine("Bird Fly.");}
}public class Dog
{public void Eat(){Console.WriteLine("Dog Eat.");}public void Sleep(){Console.WriteLine("Dog Sleep.");}public void Run(){Console.WriteLine("Dog Run.");}
}public class Fish
{public void Eat(){Console.WriteLine("Fish Eat.");}public void Sleep(){Console.WriteLine("Fish Sleep.");}public void Swim(){Console.WriteLine("Fish Swim.");}
}public class Raiser
{public void RaiseDog(){Dog dog = new Dog();dog.Eat();dog.Sleep();}public void RaisBird(){Bird bird = new Bird();bird.Eat();bird.Sleep();}public void RaisFish(){Fish fish = new Fish();fish.Eat();fish.Sleep();}
}class Program
{static void Main(string[] args){Raiser rar = new Raiser();rar.RaiseDog();// Dog Eat.// Dog Sleep.rar.RaisBird();// Bird Eat.// Bird Sleep.rar.RaisFish();// Fish Eat.// Fish Sleep.}
}
方案二:
public class Bird
{public void Eat(){Console.WriteLine("Bird Eat.");}public void Sleep(){Console.WriteLine("Bird Sleep.");}public void Fly(){Console.WriteLine("Bird Fly.");}
}public class Dog
{public void Eat(){Console.WriteLine("Dog Eat.");}public void Sleep(){Console.WriteLine("Dog Sleep.");}public void Run(){Console.WriteLine("Dog Run.");}
}public class Fish
{public void Eat(){Console.WriteLine("Fish Eat.");}public void Sleep(){Console.WriteLine("Fish Sleep.");}public void Swim(){Console.WriteLine("Fish Swim.");}
}public enum AnimalType
{Dog,Bird,Fish
};public class Raiser
{public void Raise(AnimalType alt){switch (alt){case AnimalType.Bird:Bird bird = new Bird();bird.Eat();bird.Sleep();break;case AnimalType.Dog:Dog dog = new Dog();dog.Eat();dog.Sleep();break;case AnimalType.Fish:Fish fish = new Fish();fish.Eat();fish.Sleep();break;}}
}class Program
{static void Main(string[] args){Raiser rar = new Raiser();rar.Raise(AnimalType.Dog);// Dog Eat.// Dog Sleep.rar.Raise(AnimalType.Bird);// Bird Eat.// Bird Sleep.rar.Raise(AnimalType.Fish);// Fish Eat.// Fish Sleep.}
}
方案三:
public abstract class Animal
{public int Age;public double Weight;public abstract void Eat();public abstract void Sleep();
}public class Bird : Animal
{public override void Eat(){Console.WriteLine("Bird Eat.");}public override void Sleep(){Console.WriteLine("Bird Sleep.");}public void Fly(){Console.WriteLine("Bird Fly.");}
}public class Dog : Animal
{public override void Eat(){Console.WriteLine("Dog Eat.");}public override void Sleep(){Console.WriteLine("Dog Sleep.");}public void Run(){Console.WriteLine("Dog Run.");}
}public class Fish : Animal
{public override void Eat(){Console.WriteLine("Fish Eat.");}public override void Sleep(){Console.WriteLine("Fish Sleep.");}public void Swim(){Console.WriteLine("Fish Swim.");}
}public class Raiser
{public void Raise(Animal al){al.Eat();al.Sleep();}
}class Program
{static void Main(string[] args){Raiser rsr = new Raiser();rsr.Raise(new Dog());// Dog Eat.// Dog Sleep.rsr.Raise(new Bird());// Bird Eat.// Bird Sleep.rsr.Raise(new Fish());// Fish Eat.// Fish Sleep.}
}
后台回复「搜搜搜」,随机获取电子资源!
欢迎关注,请扫描二维码:
相关文章:

Centos7安装编译安装zabbix2.219及mariadb-5.5.46
mariadb-5.5.46的安装: 首先下载mariadb-5.5.46-linux-x86_64.tar.gz,然后使用tar -xf mariadb-5.5.46-linux-x86_64.tar.gz -C /usr/local目录下 添加数据库组 # groupadd mysql 添加数据库用户 # useradd -g mysql mysql cd /usr/local ln -sv…

软件测试开发:常见测试类型概念
软件测试是软件开发中非常重要的一个环节,软件测试工程师需要对每个环节进行严格把控,才能保证系统在每个阶段得以控制。下面小编就为大家详细介绍一下软件测试开发:常见测试类型概念的相关内容。 软件测试开发:常见测试类型概念: (1)边界测试…

技术图文:C#语言中的泛型 I
C#语言中的泛型 I 知识结构: 1. 泛型概述 泛型广泛应用于容器(Collections)和对容器操作的方法中。 从 .NET Framework2.0 开始,微软提供了一个新的命名空间System.Collections.Generic,其中包含了一些新的基于泛型…

ubuntu搭建svn、git遇到的问题及解决办法
不错的git笔记博客: http://www.cnblogs.com/wanqieddy/category/406859.html http://blog.csdn.net/zxncvb/article/details/22153019 Git学习教程(六)Git日志 http://fsjoy.blog.51cto.com/318484/245261/ 图解git http://my.oschina.net/x…

webstorm同时打开多个project方法
曾经多次碰到过想要打开多个project的时候,可每次打开其他项目时,必须选择新窗口还是替换次窗口,如果新窗口的话就无法跟现在的项目在同一个webstorm中同时进行编辑,需要来回切换窗口,很是不方便,今天无意中…

什么业务场景适合使用Redis?
Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年…

Linux基础知识汇总(2)...持续更新中
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566软件安装: {软件安装的几种形式 rpm 由厂商提供二进制包 yum rpm源的前端管理器 src 源码包configure安装 bin 包含rpm和shell将安装一步执…

技术图文:C#语言中的泛型 II
C#语言中的泛型 II 知识结构: 6. 泛型接口 泛型类与泛型接口结合使用是很好的编程习惯,比如用IComparable<T>而非IComparable,以避免值类型上的装箱和拆箱操作。若将接口指定为类型参数的约束(接口约束)&#…

linux档案权限
Linux 下的档案当你对一个档案具有w权限时,你可以具有写入/编辑/新增/修改档案的内容的权限, 但并丌具备有删除该档案本身的权限!对二档案的rwx来说, 主要都是针对『档案的内容』而觊,不档案档名的存在不否没有关系喔&…

新手UI设计师需要掌握的知识和技能
UI设计岗位在近几年的需求是越来越高的,很多零基础学员都开始学习UI设计技术,那么想要成为一名合格的UI设计师,新手UI设计师需要掌握的知识和技能是比较要会的,来看看下面的详细介绍。 新手UI设计师需要掌握的知识和技能ÿ…

数据结构与算法:04 C#面向对象设计 II
04 C#面向对象设计 II 知识结构: 5、属性 例1:属性概念的引入(问题) public class Animal {public int Age;public double Weight;public bool Sex;public Animal(int age, double weight, bool sex){Age age;Weight weight;S…

SharePoint迁移和升级方案
这是之前针对SharePoint迁移和升级写的方案,去掉了敏感的部分,共大家交流吧。SharePointMigrationSolution转载于:https://www.cnblogs.com/zhaojunqi/archive/2012/04/12/2444803.html

零基础如何掌握web前端开发技能
很多零基础学员想要进入到互联网行业都会选择web前端做首选技术语言来学习,但是学习web前端不是那么容易的,想要成为一名合格的web前端工程师,所要掌握的技能一定要会,下面小编就为大家详细的介绍一下零基础如何掌握web前端开发技…
数据结构与算法:05 Leetcode同步练习(一)
Leetcode同步练习(一) 题目01:两数之和 题号:1难度:简单https://leetcode-cn.com/problems/two-sum/ 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个整数,…

用Asp.net实现简单的文字水印
经常看见MOP上有人贴那种动态的图片,就是把一个字符串作为参数传给一个动态网页,就会生成一个带有这个字符串的图片,这个叫做文字水印。像什么原来的熊猫系列,还有后来的大树和金条,都挺有意思。这东西看着挺好玩的&am…

yum国内镜像
Centos-7修改yum源为国内的yum源 国外地址yum源下载慢,下到一半就断了,就这个原因就修改它为国内yum源地址 国内也就是ali 与 网易 以centos7为例 ,以 修改为阿里的yum源 先确定有wget 备份本地yum源 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo_…

HTML的标签分为哪几类?各标签语法格式是怎样的?
HTML的标签分为哪几类?各标签语法格式是怎样的?相信大家在学习HTML课程的时候,有讲到这方面的知识,根据标签的组成特点,通常将HTML标签分为两大类,分别是“双标签”、“单标签”,对它们的具体介绍如下。 1.双标签 双…

数据结构与算法:06 线性表
06 线性表 知识结构: 1. 线性表的定义与操作 1.1 线性表的定义 线性表(Linear List)是由n(n≥0)n (n≥0)n(n≥0)个相同类型的数据元素a0,a1,⋯,an−1a_0,a_1,⋯,a_{n-1}a0,a1,⋯,an−1组成的序列。即表中除首尾元素外,其…

MySQL提权简单方法
前不久网上公开了一个MySQL Func的漏洞,讲的是使用MySQL创建一个自定义的函数,然后通过这个函数来攻击服务器。最早看到相关的报道是在o-otik上,但是公布的是针对 Unix系统的Exploit,并且成功率也不是很高.而近期,国内有高手放出针对Win系统的相关文章,于是我马上找来与朋友一同…

转载LINQ优点 自己学习用的
这几天在读一本LINQ方面的书《Essential LINQ》,在这里和大家分享下。 由于对LINQ的深入总结需要大量的篇幅,因此在这里分成几个部分来讲。 (*我看《Essential LINQ》是英文版的,有些名词不能翻译成正统的中文解释请给予谅解) LIN…

什么是Python?好学吗?
互联网IT行业是很多人都比较关注的行业,大部分都想学习IT技术进入到这个行业,Python编程语言在近几年是多数人的选择,那么什么是Python?好学吗?具体来看看下面的详细介绍吧。 一、什么是python 网络上对python的解释是一门解释型、面向对象…

数据结构与算法:07 Leetcode同步练习(二)
目录 题目01:回文数题目02:x 的平方根题目03:爬楼梯题目04:买卖股票的最佳时机题目05:买卖股票的最佳时机 II题目06:跳跃游戏题目07:三数之和题目08:最接近的三数之和题目09&#x…

(五)Docker镜像和容器
之所以在之前没有讲什么是镜像和容器是因为如果你没有一个最初的认识,那么你就很难理解镜像和容器以及它们的区别。我相信在前面一章中的讲述中,你应该稍有体会容器是基于镜像构建的,同时构建了容器之后如果不删除就会一直存在,而…

翻译-高质量JavaScript代码书写基本要点(转载)
by zhangxinxu from http://www.zhangxinxu.com本文地址:http://www.zhangxinxu.com/wordpress/?p1173 原文作者:Stoyan Stefanov原文链接:The Essentials of Writing High Quality JavaScript 翻译编辑:张鑫旭//zxx: 俗不可耐的…

学习ui设计的流程是什么
UI设计在如今的市场行情中是很多企业都必不可少的一个技术岗位,UI设计是比较注重自身产品的用户体验的,想要学习UI设计,一定要做足功课,下面小编就为大家详细的介绍一下学习ui设计的流程是什么? 学习ui设计的流程是什么?总体进程…
数据结构与算法:08 Leetcode同步练习(三)
目录 题目01:合并两个有序链表题目02:删除排序链表中的重复元素题目03:环形链表题目04:反转链表题目05:删除链表中的节点题目06:两数相加题目07:删除链表的倒数第N个节点题目08:两两…

Linux之进程管理
程序是保存在外部存储设备(如硬盘)中的可执行机器代码和数据的集合。而进程是在CPU及内存中处于动态执行状态的计算机程序。每个程序启动后会产生一个或多个进程,如httpd程序,当有大量用户访问Web页面时,httpd程序会产…

win8 metro 拖拽重排grid
0.1 http://1.metrowin8.sinaapp.com/Code/index.html 拖拽重排实现思路 : 1.初始化拖拽对象时,上传拖拽对象中心点信息(包括id,className) 2.鼠标按下时,制造一个假的拖拽对象 3.鼠标放开时,计算鼠标与拖拽对象中心点的距离&…

什么是AngularJS?它有哪些特性?
AngulaJS是款非常优秀的JasSetpsn结构化框架,可以用来构建单页面应用程序,2009年,AngularJS由Misko Hevery等人创建,后来被Google收购,该技术已经被用于Coogle旗下的多款产品开发当中。开发人员不仅可以使用和扩展HTML语言的特性。而且可以更…

ELK安装文档及相关优化
前言:随着硬件成本的不断低廉,我们可以存储更多数据内容,也会对各数据加以利用,其中一项很重要的数据内容便是日志文件,无论是访问日志还是系统日志或是应用日志,都显得十分重要,而怎么加以利用…