码迷,mamicode.com
首页 > Windows程序 > 详细

15-01-18 C# 面向对象 13

时间:2015-01-18 13:02:24      阅读:275      评论:0      收藏:0      [点我收藏+]

标签:

要进入debug文件,除了右键进入资源管理器之外,也可以在解决方案资源管理器右上方,点击显示全部文件按钮,会列出当前项目的文件列表,把要放的文件放入debug即可;

多态的好处 1,减少代码量 2.屏蔽各个子类之间的差异,写出通用的代码;

C#中的访问修饰符;

public 公开的,公共的

private 私有的,只能在当前类的内部访问

protect 受保护的, 只能在当前类的内部以及该类的子类中访问,

internal 只能在当前项目中访问,在同一项目中,internal和public的访问修饰符是一样的,

protected inrernal  它的权限是protected权限加上internal的权限;

修饰类的访问修饰符只有两个,public internal,如果不写类的访问修饰符,默认是internal,表示只有在当前项目中才能访问这个类,出了这个项目就访问不到了,因此我们为了 让在别的项目里也能访问到这个类的话,我们在建类的时候在类的前面加上public

internal的权限和protected相比,在同一个项目中。Internal的权限要比protected大,但是一旦垮了项目,protected的权限要比internal的权限大,因为不同项目之间依然存在继承关系, internal访问不到了,但是由于继承关系,protected成员依然可以跨项目访问,(跨项目的时候1要添加引用,2要添加命名空间);

在命名空间中定义的元素无法显示的声明为private,protected,protected internal;

类中的成员五个访问修饰符都可以定义;

可访问性不一致,子类的访问权限不能高于父类的访问权限;原因是会暴漏父类的成员;

简单工厂设计模式 设计这个项目的一种方式; 有一个牛人把我们写程序当中经常会遇到的问题,没一个问题都写成了一个解决方案;这一个解决方案就是一个设计模式,有23个设计模式;如果把23种设计模式从头到尾敲一遍就是大牛了, 设计模式帮助我们解决在日常开发中遇到的问题,

简单工厂设计模式最核心的就是工厂,这个工厂最后根据用户的输入来返回一个(笔记本对象),但是用户输入的东西是不知道的,只能给他返回一个父类,但是父类里面装的是子类的对象,

重写父类的方法的时候,子类的方法名字和父类被重写方法的名字是一样的,

public abstract class NoteBook

{   

  public abstract void SayHello();

}

public class Lenovo : NoteBook

{   

  public override void SayHello()   

  {       

    Console.WriteLine("我是联想");

  }

}

public class IBM : NoteBook

  {   

    public override void SayHello()   

     {       

      Console.WriteLine("我是IBM");  

      }

  }

public class Acer : NoteBook

  {   

    public override void SayHello()   

    {       

      Console.WriteLine("我是宏基");

      }

}

public class Dell : NoteBook

  {   

    public override void SayHello()   

     {       

      Console.WriteLine("我是戴尔");   

      }

  }

public class Test

{   

public static NoteBook GetNoteBook(string brand) //简单工厂的核心,根据用户的输入创建对象赋值给父类;其实还有一个核心的还是用抽象类实现了多态;     

 {      

     NoteBook nb = null;      

    switch(brand)

      {      

      case"Lenovo":

        nb = new Lenovo();       

        break;      

      case"IBM":

        nb = new IBM();       

        break;      

       case"Acer":

        nb = new Acer();       

        break;      

      case"Dell":

        nb = new Dell();       

         break;  

    }      

    return nb;                //简单工厂最核心的代码部分;

  }

}

string brand = Console.ReadLine();

NoteBook nb = GetNoteBook(brand);

nb.SayHello();

值类型:int double char decimal bool enum struct

引用类型:string 数组 自定义类 集合 object 接口

值类型在复制的时候,传递的是这个值的本身,

person p1 = new person();

p1.Name = "张三";

person p2 = p1;     

//这行代码表示p1,p2指向同一个对象(p1的new person());现在只要改变p1或者p2的其中任何一个,(p1的new person())其中另外一个值就会变;                    

//简单的说,p1和p2指向同一块内存,这个时候只要改变p1,那么p2也跟着改变,只改变p2,那么p1也跟着改变; p2.Name = "李四"; //把p2变成了李四,那么p1也成了李四; Console.WriteLine(p1.Name); 输出的是"李四";

引用类型在复制的时候,传递的是对这个对象的引用(地址);

person p = new person();

p.Name = "张三";

Test(p);

Console.WriteLine(p.Name);  //p.Name 为李四;

public static void Test(person pp)

{  

 person p = pp;  

 p.Name = "李四";

}

不管是形参还是实参都是实实在在在内存中占空间的,

string s1 = "张三";

string s2 = s1;

s2 = "李四";

Console.WriteLine(s1);  //张三 

虽然是引用类型,但是字符串的不可变性;

Console.WriteLine(s2);  //李四

 

int number = 10;

TestTwo(number);

Console.WriteLine(number);   //输出10;

public static void TestTwo(int n)

{  

n+=10;

}

 

int number = 10;

TestTwo( ref number);

Console.WriteLine(number);   //输出20;

public static void TestTwo( ref int n)

{

  n+=10;

}

ref能够把一个变量,以参数的形式带到一个方法中进行改变,再将改变完成后的值带出方法,

ref的原理是把值类型的值传递变为引用传递,使得两个值类型共占一块内存空间(地址);

要看变量在栈上的地址,设个断点,运行,然后在即时窗口输入&变量名,按回车;

序列化:就是将对象转换为二进制;

反序列化:就是将二进制转换为对象,

序列化和反序列化的作用:传输数据;

在网络中不管传输什么内容,先把传输的内容二进制,对方接收到的也是二进制,它需要干另外一件事就是反序列化;把这个二进制 反序列化为对象;

public class Person

{    

  private string _name;       

  public string Name  

     {        

    get{return _name;}        

    set{_name = value} 

     }        

     private int  _age;    

     public int Age;

    {       

     get{return _age;}    

     set{_age = value}   

    }         

     private char  _gender;    

     public char Gender   

    {      

      get{return _gender;}     

      set{_gender = value}   

    }

}

序列化的第一步 1.将这个类标记为可以被序列化的,在一个类的上面写上[Serializable]指示一个类可以被序列化,此类不可以被继承;

只有被[Serializable]标记的类创建出来的对象   才能被序列化;

person p = new person();

p.Name = "张三";

p.Age = 19;

p.Gender = ‘男‘;

using(FileStream fsWrite = new FileStream(@"C:\Users\hhs\Desktop\1.txt",FileMode.OpenOrCreate,FileAccess.Write))

{    //开始序列化对象   

    BinaryFormatter bf = new BinaryFormatter();  

    bf.Serializa(fsWrite,p);

}

    Console.writeline("序列化成功");

  //反序列化

   Person p;

using(FileStream fsRead = new FileStream(@"C:\Users\hhs\Desktop\1.txt",FileMode.OpenOrCreate,FileAccess.Read))

{   

    BinaryFormatter bf = new BinaryFormatter();  

    p = (Person)bf.Deserializa(fsRead);

}

Console.WriteLine(p.Name);

Console.WriteLine(p.Age);

Console.WriteLine(p.Gender);

学一个东西一定要知道它是干嘛用的;

在一个命名空间下不允许定义一个重名的类,也不允许在一个类中定义重名的方法(前提是它们没有重载)

我们有的时候必须要在一个命名空间下定义重名的类,比如三个人共同做一个项目,这时候都要写person类,

public partial class Person

{    

}

public partial class Person

{    

}

//这两个都是person类的一部分,共同组成了person类,这样的话就可以同时对person类进行编程,而且一个部分类的成员在另一个部分类里面全都可以访问;  但是部分类里面不允许有重名的方法(不包括重载)

public sealed class Person   //密封类最大的特点就是不能被继承;但是能继承别的类;

{   

}

重写toString()方法; 如果直接对象.ToString(),那么打印出来的是它的命名空间;

所有的类都能ToString(),因为所有类都直接或间接继承object类,ToString()是object类的方法;

因为子类不能调用父类的抽象方法,但是子类可以调用父类的虚方法,所以ToString()是虚方法,因为我们可以重写它,子类可以重写父类的虚方法;(当然子类也可以重写父类的抽象方法)

public class Person

{  

  public  override string Tostring()

    {  

       return  "Hello World";  

    }

}

重写了Tostring()方法,但是只是Person类的ToString();其他类的ToString()依旧没变;

接口:

public class Person

{  

     public void CHLSS()  

    {    

      Console.WriteLine("我是人类,我可以吃喝");  

    }

}

//public class NBAPlayer

//{

//  public void KouLan()

// {

//     Console.WriteLine("我可以扣篮");

//  }

}

public class Student : Person,IKouLanable

{  

    public void KouLan()  

    {   

      Console.WriteLine("我也可以扣篮");  

    } 

}

//由于Student继承了Person类,因此他可以吃喝,但是同时他也想实现可以扣篮,由于继承具有单根性,不能既继承Person,又继承NBAPlayer,这时候我们可以考虑将NBAPlayer定义成一个接口

public  interface IKouLanable 

//以I开头以able结尾表示一种能力

{  

  void KouLan();

}

定义成接口之后,Student就可以既继承Person,又可以继承NBAPlayer接口了,

一个类继承了接口,必须要实现这个接口的成员,快速实现Alt+shift+F10

什么时候需要用到接口, 1.类需要实现多继承;因为类是不允许多继承的;

接口就是一个规范,能力;

接口:

[public] interface I...able

{  

成员;

}

public interface IFlyable

{  

void Fly(); //比抽象方法更省事;

接口中的成员不允许添加访问修饰符;默认就是public,接口中没有方法体,类中成员不添加默认就是private               

//抽象类中普通的方法可以有方法体,但是抽象函数不可以,但是在接口中不允许写有方法体的成员;               

//接口中不能包含字段;接口不是用来存储数据的,存储数据用类来存,  

string Test();  

string Name  

{    

 get;    //自动属性;  接口中能写方法,但是不能有方法体,属性的本质是get,set方法,因为自动属性没有get,set方法体,因此,接口中可以有自动属性,  

   set;    //get和set本质上也是函数,因此这个自动属性和上面的fly没有区别;

   }

}

private string _name;

public string Name

{  

   get{return _name;}

   set{_name = value;}

}

public int Age

{  

  get;  

      set;

}

自动属性,虽然我们没有给它写字段,但是在编译的时候会自动的给我们生成一个字段; 自动属性和普通属性的区别,一个有字段,有方法体 ;一个没有字段,没有方法体; 自动属性的缺点,不能在属性里面进行值的限定了,不允许写方法体,那么要对值进行限定就要使用构造函数了;各有各的好处; 自动属性本质上是两个函数,

接口中可以有方法和属性,还可以有索引器(索引器还没学过;)这三个东西本质上都是方法;接口中只能有方法;

接口是一种规范,只要一个类继承了一个接口,这个类就必须实现这个接口中所有的成员;

一个类中,去实现接口中的方法,没有override,有override是重写;

为了多态,接口不能被实例化,也就是说,接口不能new(不能创建对象);

抽象类,静态类,接口不能被实例化;抽象类,接口由于没有对方法进行实现,因此即使创建了对象也没有意义; 因此要实现多态的话,要去指向一个子类对象; 

//实现多态的时候,3种方法一般都是父类对象装子类;三种方式都是在继承的基础上实现多态;

IFlyable fly = new Person();

fly.Fly();

public class Person:IFlyable

{  

public void Fly()  

  {    

   Console.WriteLine("人类在飞");  

 }

}

public class Bird:IFlyable

{  

   public void Fly()  

    {    

       Console.WriteLine("鸟类在飞");  

    }

}

public interface IFlyable

   {  

     void Fly();

   }

接口中的成员不能加“访问修饰符”,接口中的成员访问修饰符为public,不能修改;

接口中的成员不能有任何实现,这个很我们的抽象类当中的抽象函数是一样的,(都是光说不做,交给子类去做,接口只是定义了一组未实现的成员);

接口中只能有方法,属性,索引器,事件,这四个本质上都是方法,不能有“字段”和构造函数;不能有字段是因为接口不是用来存储数据的,它表示一种规范,一种能力;

因为接口不能创建对象,因此即使有构造函数没有用

接口与接口之间可以继承,并且可以多继承;类就不能多继承;

public interface M1

{  

  void Test1();

}

public interface M2

{  

  void Test2();

}

public interface M3

 {  

   void Test3();

 }

public interface SuperInterface:M1,M2,M3

{  

}

public class Car : SuperInterface  //继承一个大接口,他所继承的接口都要实现;

{  

   public  void Test1();  

    {   

     }

   public  void Test2();  

    {   

    }

    public  void Test3();  

    {   

     }

}

接口并不能去继承一个类,而类可以继承接口(接口只能继承接口。而类既可以继承接口,也可以继承类)

实现接口的子类必须实现该接口的全部成员;

一个类可以同时继承一个类并实现多个接口,如果一个子类同时继承了父类A,并实现了接口IA,那么语法上A必须写在IA的前面; class MyClass:A,IA{},因为类是单继承的.

说是说面向对象的编程,但是很多情况下其实就是面向接口的编程;

比如说手机中的天气预报,有很多个APP都有天气;但是这些数据源头是中央气象台; 中央气象台对外提供了一个接口,那么我只要实现这个接口中的成员,按照指定的要求去做,那么就可以得到天气信息;

支付宝之前只有淘宝有,很多网站现在都有,因为也实现了接口,所以现在基本上就是面向接口编程;

麻雀会飞, 鹦鹉会飞 鸵鸟不会飞 企鹅不会飞  直升机会飞

用多态来实现虚方法,抽象类,接口;

IFlyable fly = new YingWu()//new MaQue()//new Plane();

fly.Fly();

public class Bird

{  

  public double Wings  

  {    

     get;   

     set;

   }

   public void EatAndDrink()   

   {      

       Console.WriteLine("我会吃喝");   

    }  

  }

public class MaQue:Bird,IFlyable

  {  

     public void Fly()   

     {   

       Console.WriteLine("麻雀会飞");   

     }

 }

public class YingWu:Bird,IFlyable,ISpeakable

  {

     public void Fly()   

      {   

        Console.WriteLine("鹦鹉会飞");  

       }      

    public void Speak()   

    {   

       Console.WriteLine("鹦鹉可以学人类说话");

    }

}

public class TuoBird:Bird

  {  

   }

public class QQ:Bird

  {  

  }

public class Plane:IFlyable

  {  

     public void Fly()

    {  

      Console.WriteLine("直升飞机转动螺旋桨飞行");  

    }

}

public interface IFlyable

   {

      void Fly();

   }

public interface ISpeakable

   {  

    void Speak();

   }

 

//显示实现接口就是为了解决方法的重名问题;

public class Bird:IFlyable

 {  

     public void fly()  

     {   

        Console.WriteLine("鸟会飞");   

     }  

     void IFlyable.Fly()             //显示实现接口; 不允许加访问修饰符,类中的成员默认是private,接口中默认是public

    {   

      Console.WriteLine("我是接口的飞");    //这个其实跟抽象类一样,调用的是父类的函数,只不过在子类中重写了;  

    }    

  }

public interface IFlyable

 {  

    void Fly();

}

Bird自己的方法和接口中的方法重名了,

IFlyable fly = new Bird();

fly.Fly();           //接口的飞  本质上访问的是接口的Fly,只不过接口的Fly被子类实现了;接口的Fly是public的

Bird bird = new Bird();

bird.Fly();         //自己的飞

在我提供给你的这几个类当中,如果说你能抽象出一个父类,并且父类当中必须写上这几个子类共有的方法,然后你不知道如何去写这个方法,这个时候要用抽象类

反之,抽象出来的父类可以写,还需要创建这个父类的对象,这个时候用虚方法,

如果这几个类里面根本找不出父类,但是它们都有共同的行为,共同的能力,这个时候拿接口实现多态;

比如鸟和飞机没有父类,但是它们都会飞,这个飞只能写成接口,不能写个父类去继承,因为根本提不出父类,

//真的鸭子会游泳, 木头鸭子不会游泳,橡皮鸭子会游泳; 一看到会干什么,能干什么侧重于能力,能力就由接口来做,把真鸭子作为父类,但是不能在父类里面写游泳函数,因为木鸭子不会,不能写抽象方法,因为真的鸭子需要被创建 对象,真鸭子有意义,虚方法也不合适,因为木鸭子不会游泳,所以用接口最合适;

public class RealDuck:ISwimming

{  

    public void Swim()  

   {    

     Console.WriteLine("真的鸭子靠翅膀游泳");  

       }

}

public class MuDuck    

 {  

 }

public class XPDuck:ISwimming    

//不写方法体也不会报错,因为继承于RealDuck了,RealDuck里面有Swim了,但是由于他们游泳的方式不一样,因此没必要继承RealDuck

{  

   public void Swim()  

   {   

    Console.WriteLine("橡皮鸭子漂着游泳");  

      }

}

public interface Iswimming

  {  

     void Swim();

  }

ISwiming swim = new RealDuck()//new XPDuck() ;

swim.Swim();

超市收银管理系统,商品类,仓库类,超市类;

类前面不加访问修饰符,默认是Internal表示同一个项目中可以访问;

第一步,写商品的父类ProductFather;写价格,数量,编号三个自动属性;再写一个父类的构造函数

GUID能够帮助我们产生全世界独一无二的编号,GUID是个结构, Guid.NewGuid().ToString();

第二步,写商品的子类继承父类;写出每个子类的构造函数;

第三部,收银系统中最重要的一个类,仓库类;

存储货物;

List<ProductFather>  list1 = new  List<ProductFather>(); //这样写表示把所有的商品都堆在一堆了,没有体现出分门别类存储商品;所有货物都混在一起,拿的时候不好拿;

List<List<ProductFather>>  list2 = new  List<List<ProductFather>>();//在集合里面又放了一个集合;List<ProductFather>这个是数据的类型;

在给list1添加数据的时候,可以把货物对象直接添加进来,坏处是取得时候很麻烦;取得时候不知道哪个下标是谁;看下标对应的是哪个对象;于是乎我们想到用两个集合;

在给list2添加数据的时候只能添加一个集合进去;其实这个集合就是货架;给list2添加进去的不是商品,而是货架;

不管是list1还是list2其实都是整个仓库;

用list1存数据相当于 把商品直接扔进了仓库,在list2中添加进来的是数据的集合,仓库里的货架是货物的集合,所以往仓库添加数据的时候,先添加货架;

List<ProductFather>  list1 = new  List<ProductFather>();

list1[0] list1[1] list1[2]这些就是货物;//这种不好;

List<List<ProductFather>>  list2 = new  List<List<ProductFather>>();//这段代码创建出了一个仓库;

list2[0] list2[1] list2[2]这些就是货架;    

因为创建仓库的时候已经要有货架了,因此我们要创建仓库类的构造函数;

//list[0]存储宏基笔记本   list[1]存储三星手机   list[2]存储酱油   list[3]存储香蕉

public CangKu()

{  

   list.Add(new List<ProductFather>());  

   list.Add(new List<ProductFather>());  

   list.Add(new List<ProductFather>());  

   list.Add(new List<ProductFather>());  

//如果要1000个对象,就要1000行,但是我们可以通过循环创建;

}

进货:

public void JinPros(string strType,int count)

{  

    for(int i = 0 ;i < count;i++)  

    {   

      switch(strType)    

      {        

         case "Acer":

        list[0].Add(new Acer(Guid.NewGuid().ToString(),1000,"宏基笔记本"));       

        break;    

       case "SangSung":

       list[1].Add(new SangSung(Guid.NewGuid().ToString(),2000,"三星手机"));      

       break;    

        case "JiangYou":

       list[2].Add(new JiangYou(Guid.NewGuid().ToString(),10,"老抽酱油"));    

       break;   

       case "Banana":

     list[2].Add(new Banana(Guid.NewGuid().ToString()20,"大香蕉"));     

       break;   

        }

   }

}

//来货之后,我们首先创建仓库对象,然后创建Getpros方法,往里面放货物;

取货:

public ProductFather[] QuPros(string strType,int count)

{

    ProductFather[] pros = new ProductFather[conut];

     for(int i = 0;i < count; i++)

    {   

     switch(strType)    

     {      

       case:"Acer":      

      pros[i] = list[0][0];     

      list[0].RemoveAt[0];    

      break;       

     case:"SangSung":    

      pros[i] = list[1][0];      

      list[1].RemoveAt[0];   

      break;     

      case:"JiangYou":   

       pros[i] = list[2][0];     

      list[2].RemoveAt[0];    

       break;   

      case:"Banana":      

      pros[i] = list[3][0];      

      list[3].RemoveAt[0];     

      break;   

    }  

  }

    return pros;

}

 List<List<ProductFather>>  list2 = new  List<List<ProductFather>>();//这种存储数据的方式是为了分类;

展示货物,

public void ShowPros()

{  

   foreach(var item in list)

    {     

       Console.WriteLine(item[0].Name    item.count    item[0].Price);  

    }

}

 

15-01-18 C# 面向对象 13

标签:

原文地址:http://www.cnblogs.com/hhsfrank/p/4231609.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!