【C#从入门到精通】面向对象继承

01、复习

1)、Encoding.utf :UTF32 \ 7 \ 8 共同组成Unicode(国际通用编码)

byte[] buffer = File.ReadAllBytes(@"C:\b\d\抽象类特点.txt")
//将字节数组中的每一个元素都要按照我们指定的编码格式解码成字符串
//UTF-8  GB2312  GBK ASCII  Unicode
string s = Encoding.GetEncoding("GBK").GetString(buffer);
string s = Encoding.GetEncoding("其它").GetString(buffer);
string s = Encoding.UTF8.GetString(buffer);  //如果编码不同就会出现乱码

//如果没有这个文件的话 会给你创建一个 有的话 会给你覆盖掉
string str = "今天天气真不错";
//需要将字符串转换字节数组
byte[] buffer = Encoding.Default.GetBytes(str);
//写入字符串
File.WriteAllBytes(@"C:\b\d\牛呀.txt",buffer);

//读取文件
//1.按字节读取  适合读取文本和除文本外的媒体文件
ReadAllBytes();
//2.按行读取  适合读文本
string[] str = ReadAllLine(@"...\...\name.txt",Encoding.Default);
foreach(string item in str)
{
	Console.WriteLine(item);
}

//3.按文本读取
string str = ReadAllText(@"...\...\name.txt",Encoding.Default);


02、File类的读写文件

1)、当要读取的东西是以媒体文件的时候,就不能用ReadAllLine\ReadAll
2)、绝对路径和相对路径
绝对路径:通过给定的这个路径直接能在我的电脑中找到这个文件
相对路径:文件相对于应用程序的路径(将文件放在可执行目录下面)
3)、只能读写小文件,如果要读写大文件,需要使用文件流

//按行写入
File.WriteAllLines(@"...\..\text.txt",new string[]{"一","二"});
//按文本输入 会覆盖源文件
File.WriteText(@"...\...\test.txt","一二三四"*(字符串)*);

//不覆盖源文件
File.AppendAllText(@"...\...\test.txt","字符串数据");

03、List泛型集合

1)、定义类型确定了,Add(): 数据类型也去确定了
2)、返回数组的类型由List的类型决定,int --> int string–>string

List<int> list = new List<int>();
list.Add(1);
list.Add(2);
list.AddRange(new int[]{1,2,3});
for(int i = 0;i < list.count;i++)
{
	Console.WriteLine(list[i]);
}

//List泛型集合可以转换为数组
int[] num =list.ToArray();
//转换的类型取决于List声明时的数据类型
List<string> listStr = new List<string>();
string[] str = listStr.ToArray();

//将 数组 转换为 Lits 
int[] num = new int[]{1,2,3};
List<int> listInt = num.ToList();
char[] chs = new char[]{'a','b','c'};
List<char> listChar = chs.ToList();

04、装箱和拆箱

1)、
装箱:就是将值类型转换为引用值类型
拆箱:将引用值类型转换为值类型

//值类型 -->  引用类型
int n = 10;
object obj = n;
//应用类型  -->  值类型
object obj = new object();   //int - object 存在继承关系
int num = (int) obj;

2)、看两种类型是否发生了装箱或者拆箱,要看,这两种类型是否存在继承关系
存在继承关系:可能存在装箱或拆箱
如果不存在继承关系:一定不存在装箱或者开箱

//这个地方没有发生任意类型的装箱或者拆箱
string str = "123";
int num = Convert.ToInt32(str);

3)、代码中应该尽量避免装箱和开箱的出现,除影响速率

05、字典集合

1)、与Hathtable区别:键–>int;值–>string
2)、**注意:键必须是唯一的
3)、

Dictionary<int,string> dic = new Dictionary<int,string>();
dic.Add(1,"张三");
dic.Add(2,"李四");
dic.Add(3,"王五")
dic[1] = "新来的";
foreach (var item in dic.Keys)
{
	Console.WriteLine(dic[item]);
}
//一对遍历
foreach (KeyValuePair<int,string> kv in dic)
{
	Console.WriteLine("{0},{1}",kv.Key,kv.Value);
}

06、集合的三个练习

1)、

            //将一个数组中的奇数放在一个集合中,再将偶数放到另一个集合中
            //最终将两个集合合并为一个集合,并且奇数显示在左边,偶数在右边

            int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            ArrayList list = new ArrayList();
            ArrayList ouList = new ArrayList();
            ArrayList jiList = new ArrayList();

            for (int i = 0; i < nums.Length; i++)
            {
                if (nums[i] % 2 == 0)
                {
                    ouList.Add(nums[i]);
                }
                else
                {
                    jiList.Add(nums[i]);
                }
            }

            jiList.AddRange(ouList);

            foreach (var item in jiList)
            {
                Console.Write(item);
            }

2)、

            //提示用户输入一个字符串,通过foreach循环将用户输入的字符串赋值给一个字符数组
            Console.WriteLine("请输入一个字符串:");
            string input = Console.ReadLine();
            char[] chs = new char[input.Length];
            //要依次访问到string中的每个元素需要下标指引
            int i = 0;
            foreach (var item in input)   //item就是string中每个字符的项
            {
                chs[i] = item;
                i++;
            }

            foreach (var item in chs)
            {
                Console.Write(item+" ");
            }

3)、

            string str = "welcome to china";
            Dictionary<char, int> dc = new Dictionary<char, int>();
            for (int i = 0; i < str.Length; i++)
            {
                if (str[i] == ' ') 
                {
                    continue;
                }
                if (dc.ContainsKey(str[i]))
                {
                    dc[str[i]]++;
                }
                else 
                {
                    dc[str[i]] = 1;
                }
            }

            foreach (KeyValuePair<char,int> kv in dc)
            {
                Console.WriteLine("字母{0}出现了{1}次",kv.Key,kv.Value);
            }

07、使用FileStream来读写文件

1)、
FileStream 操作字节的 – 任何文件
StreamReader和StreamWriter 操作字符的 – 文本文件
2)、

//使用FileStream来读取数据
FileStream fsRead = new FileStream(@"...\...\抽象类特点",FileMode.OpenOrCreate,FileAccess.Read);
byte[] buffer = new byte[1024*1024*5];
//3.8M 5M
//返回本次实际读取到的有效字节
int r = fsRead.Read(buffer,0,buffer.Length);
//将字节数组中每一个元素按照指定的编码格式解码成字符串
string s = Encoding.Default.GetString(buffer,0,r);
//关闭流
fsRead.Close();
//释放流所占用的资源
fsRead.Dispose();
Console.WriteLine();

//使用FileStream来写入数据
using (FileStream fsWrite = new FileStream(@"C:\Users\86591\Desktop\数据流读取.txt", FileMode.OpenOrCreate, FileAccess.Write))
{
	string str = "有没有覆盖掉";
	//先把string转换成字节数组
	byte[] buff = Encoding.UTF8.GetBytes(str);
	fsWrite.Write(buff,0,buff.Length);
	
}

//(文件路径,文件操作,文件内数据操作)
//[102410245]–5M 限定读取大小,有上限,小即减少读取压力
//(buffer,0,buffer.Length) 0 - 从什么位置开始读取;buffer.Length - 上面提供的大小
//int r 返回实际读取到的有效字节数
//**GC有些资源无法回收
//实际上读的还是5M,但是解码的是750k
//大文件需要循环地区读

3)、写入数据
1、将创建文件流对象大的过程写在using当中,会自动帮助我们释放流所占用得到资源

08、使用FileStream实现多媒体文件的复制

  static void Main(string[] args)
        {
            string soucre = @"C:\Users\86591\Desktop\数据流读取.txt";
            string target = @"C:\Users\86591\Desktop\new.txt";
            CopyFile(soucre,target);
            Console.ReadKey();
        }
        public static void CopyFile(string soucre, string target)
        {
            //读
            using (FileStream fsRead = new FileStream(soucre,FileMode.Open,FileAccess.Read)) 
            {
                //写
                using (FileStream fsWrite = new FileStream(target,FileMode.OpenOrCreate,FileAccess.Write)) 
                {
                    byte[] buffer = new byte[1024 * 1024 * 5];
                    while (true)
                    {
                        int r = fsRead.Read(buffer, 0, buffer.Length);
                        fsWrite.Write(buffer, 0, r);
                        if (r == 0) 
                        {
                            break;
                        }
                    }
                }
            }
            Console.WriteLine("复制成功!");
        }

09、SreanmReader和StreamWriter

//读
using (StreamReader sr = new StreamReader(@"", Encoding.UTF8))
{
	while (!sr.EndOfStream)  //判断是否读到最后的数据流
	{
		Console.WriteLine(sr.ReadLine);
	}
}
//写
using (StreamWriter sw = new StreamWriter(@"C:\Users\86591\Desktop\new.txt",true))  //true表示继续追加
{
	sw.Write("看我有没有覆盖掉");
}

10、多态之虚方法

1)、多态的概念:让一个对象能够表现出多种的状态(类型)
2)、实现多态的3种手段:1、虚方法 2、抽象类 3、接口
3)、方法1实现
步骤
1、将父类的方法标记为虚方法,使用关键字 virtual 这个函数可以被子类重新写一遍
实现效果:直接调用被重新写的函数,哪个对象调用哪个重写方法

            Student s1 = new Student("张三", '男', 16, 1101);
            Teacher t1 = new Teacher("李四", '女', 20, 3000);
            Person[] p = { s1, t1 };
            for (int i = 0; i < p.Length; i++)
            {
                //if (p[i] is Student)
                //{
                //    ((Student)p[i]).SayHello();
                //}
                //else if (p[i] is Teacher) 
                //{
                //    ((Teacher)p[i]).SayHello();
                //}
                p[i].SayHello();
            }
public virtual void SayHello()     //在person类SayHello()加virtual
        {
            Console.WriteLine("我是人类!");
        }
public override void SayHello()    //加override
        {
            Console.WriteLine("我是学生!");
        }
 public override void SayHello() 
        {
            Console.WriteLine("我是老师!");
        }

11、抽象类

1)、当父类中的方法不知道如何 去实现的时候,可以考虑将父类写成抽象类,将方法写成抽象方法
2)、有大括号,里面没有内容叫–空实现
3)、抽象类不允许创建对象和接口
4)、

//虽然父类里面装的是子类的对象,但是表现出来的仍然是父类
Animal a = new Dog();
//所以a调用的Bark()是父类的方法
//但是是抽象类和抽象方法,已经被重写
//所以本质上调用的还是Dog类中的Bark()
a.Bark();

//print: 小狗汪汪叫

        static void Main(string[] args)
        {
            Animal a = new Dog();
            a.Bark();
            Console.ReadKey();
        }

        public abstract class Animal 
        {
            public abstract void Bark();
        }
        public class Dog :Animal
        {
            public override void Bark()
            {
                Console.WriteLine("汪汪汪");
            }
        }

12、抽象类练习(求面积和周长)

1)、抽象类特点

  1. 抽象类成员必须标记为abstract,并且不能有任何实现
  2. 抽象类成员必须在抽象类中
  3. 抽象类不能实例化
  4. 子类继承抽象类后,必须把父类中的所有抽象成员都重写(除非子类也是一个抽象类,可以不重写)
  5. 抽象成员的访问修饰符不能是private
  6. 在抽象类中可以包含实例成员,并且抽象类的实例成员可以不被子类实现
  7. 抽象类是有构造函数的,虽然不能被实例化
  8. 如果父类的抽象方法中有参数,那么,继承这个抽象类的子类在重写父类的方法时必须传入对应的参数
    如果抽象父类的抽象方法中有返回值,那么子类在重写抽象方法时,也必须要传入返回值

================
如果父类中的方法有默认的实现,并且父类需要被实例化,这是可以考虑将父类定义成一个普通类,用虚方法来实现
如果父类中的方法没有默认的实现,父类也不需要被实例化,则可以将该类的定义为抽象类

class Program
    {
        static void Main(string[] args)
        {
            Shape p = new Circle(5);
            double area = p.GetArea();
            double primeter = p.GetPrimeter();
            Console.WriteLine("Area={0},Primeter={1}",area,primeter);
            Console.ReadKey();
            
        }

    }

    public abstract class Shape
    {
        public abstract double GetArea();
        public abstract double GetPrimeter();
    }

    public class Circle : Shape
    {
        private double _r;

        public double R { get => _r; set => _r = value; }

        //public double R 
        //{
        //    //get { return _r; }
        //    //set { _r = value; } 
        //    get => _r;
        //    set => _r = value;
        //}
        public Circle(double r)
        {
            this.R = r;
        }
        public override double GetArea()
        {
            return Math.PI * R * R;
        }

        public override double GetPrimeter()
        {
            return Math.PI * R * 2;
        }
    }

    public class Square : Shape
    {
        private double _height;
        private double _weigh;

        public double Height { get => _height; set => _height = value; }
        public double Weigh { get => _weigh; set => _weigh = value; }

        public Square(double height, double weigh)
        {
            this.Height = height;
            this.Weigh = weigh;
        }

        public override double GetArea()
        {
            return Height * Weigh;
        }

        public override double GetPrimeter()
        {
            return (Height + Weigh) * 2;
        }
    }

13、穆尼移动硬盘、U盘、MP3

  1. 用多态来实现 将 移动银盘或者U盘或者MP3查到电脑上进行读写数据
    class Program
    {
        static void Main(string[] args)
        {
            //方法1
            //MobieStorage ms = new UPDisk();//new MP3Disk();
            //Computer cp = new Computer();
            //cp.CpuRead(ms);
            //方法2
            MobieStorage ms = new UPDisk();
            Computer cp = new Computer();
            //将ms传入字段里面
            cp.Ms = ms;
            cp.CpuRead();
            cp.CpuWrite();

            Console.ReadKey();

        }
    }

        public abstract class MobieStorage
        {
            public abstract void Read();
            public abstract void Write();
        }
        public class MobieDisk : MobieStorage
        {
            public override void Read()
            {
                Console.WriteLine("这是移动硬盘的读取");
            }
            public override void Write()
            {
                Console.WriteLine("这是移动硬盘的写入");
            }
        }
        public class MP3Disk : MobieStorage
        {
            public override void Read()
            {
                Console.WriteLine("这是MP3的读取");
            }
            public override void Write()
            {
                Console.WriteLine("这是MP3的写入");
            }
            public void PlayMusic() 
            {
                Console.WriteLine("开始播放音乐");
            }
        }
        public class UPDisk : MobieStorage
        {
            public override void Read()
            {
                Console.WriteLine("这是U盘的读取");
            }
            public override void Write()
            {
                Console.WriteLine("这是U盘的写入");
            }
        }
    public class Computer 
    {
        private MobieStorage ms;

        public MobieStorage Ms { get => ms; set => ms = value; }



        //方法1
        //public void CpuRead(MobieStorage ms) 
        //{
        //    ms.Read();
        //}
        //public void CpuWrote(MobieStorage ms) 
        //{
        //    ms.Write();
        //}

        public void CpuWrite() 
        {
            Ms.Write();
        }
        public void CpuRead() 
        {
            Ms.Read();
        }
    }

14、最后小结

15、复习-1

16、C#中的访问修饰符

  1. C#中的访问修饰符
    public
    private
    protected:受保护的,只能在当前的内部以及该类的子类中访问
    internal:默认是internal,只能在当前的项目中可以访问
    protected internal :
    1)、能够修饰类的访问修饰符只有两个:public 、 internal
    2)、在同一个项目中,internal和public的权限是一样的
    3)、可访问性不一致
    子类的访问权限不能高于父类的访问权限,会暴露父类的成员(类的传递性)

17、简单工厂设计模式

  1. 设计模式:设计这个项目的一种方式
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("请输入你要的牌子:");
            string input = Console.ReadLine();
            //返回一个子类对象赋值给父类
            NoteBook nb = GetNote(input);
            nb.SayHello();
            Console.ReadKey();

        }
        /// <summary>
        /// 简单工厂的核心 根据用户的输入创建对象赋值给父类
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static NoteBook GetNote(string input) 
        {
            NoteBook nb = null;
            switch (input) 
            {
                case "Acer":
                    nb = new Acer();
                    break;
                case "Lenovo":
                    nb = new Lenovo();
                    break;
                case "Dell":
                    nb = new Dell();
                    break;
            }
            return nb;
        }
    }
    public abstract class NoteBook
    {
        public abstract void SayHello();
    }
    public class Acer : NoteBook
    {
        public override void SayHello()
        {
            Console.WriteLine("我是红星笔记本");
        }
    }
    public class Lenovo : NoteBook
    {
        public override void SayHello()
        {
            Console.WriteLine("我是联想笔记本");
        }
    }
    public class Dell : NoteBook
    {
        public override void SayHello()
        {
            Console.WriteLine("我是外星人笔记本");
        }
    }

18、值传递和引用传递

  1. 值类型:int doublie char decimal bool enum struct
  2. 引用型:string 、数组、类、集合、object 、 接口
  3. 值类型在复制的时候,传递的是这个值的本身;引用类型在复制的时候,传递的是对这个对象的引用
  4. 不是将p1这个对象给了p2,而是将p1的***地址***复制一份给了p2
    在这里插入图片描述
Person p = new Person();
p.Name = "张三";
Test(p);
Console.WriteLine(p.Name);

public static void Test(Person pp)
{
	//在栈中新声明了个p
	Person p = pp;
	p.Name = "李四";
}

//print:
//李四

在这里插入图片描述

  1. string类型的不可变性,跟别的引用类型不同
string s1 = "张三";
string s2 = s1;
s2 = "李四";
Console.WriteLine(s1);
Console.WriteLine(s2);
//print:
//张三
//李四
  1. ref将栈中的n1地址复制一份给了n2,相当于n1,n2之间的间隔消失,变成处于同一块空间中
int n1 = 10;
Test(n1);
Console.WriteLine(n1);

public static void Test(ref int n2)
{
	n2 = 20;
}

//print:
//n1 = 20

19、序列化和反序列化

  1. 序列化:就是将对象转换为二进制
    反序列化:就是将二进制转换为对象
  2. 作用:传输数据
  3. 序列化步骤
    1)、将这个类标记为可以被序列化 —— [Serializable]
class Program
    {
        static void Main(string[] args)
        {
            //将p这个对象 传输给对方的电脑
            //Person p = new Person();
            //p.Name = "张三";
            //p.Gender = '男';
            //p.Age = 18;

            //using (FileStream fsWrite = new FileStream(@"C:\Users\86591\Desktop\new.txt", FileMode.OpenOrCreate, FileAccess.Write))
            //{
            //    //开始序列化对象
            //    BinaryFormatter bf = new BinaryFormatter();
            //   //Serialize自动将fsWrite.Write();执行了
            //    bf.Serialize(fsWrite, p);
            //}
            //Console.WriteLine("序例化成功");

            //接受对方发送过来的二进制 反序列化成对象
            Person p = new Person();
            using (FileStream fsRead = new FileStream(@"C:\Users\86591\Desktop\new.txt", FileMode.OpenOrCreate, FileAccess.Read))
            {
                BinaryFormatter bf = new BinaryFormatter();
                p = (Person)bf.Deserialize(fsRead);
            }
            Console.WriteLine("{0},{1},{2}",p.Name,p.Gender,p.Age);
            Console.ReadKey();
        }
    }

    [Serializable]
    public class Person
    {
        string _name;
        char _gender;
        int _age;

        public string Name { get => _name; set => _name = value; }
        public char Gender { get => _gender; set => _gender = value; }
        public int Age { get => _age; set => _age = value; }
    }

20、部分类

  1. public partial class Person{}; //使得两个同名的类可以在同意项目下
  2. 在一个类中声明的私有成员,在另外一个类中也能使用
  3. 不能声明相同的成员

21、密封类

  1. 使用关键字:sealde
    密封类特点:不能被其它类继承,但是可以继承其它类
public sealed class Person
{

}

public class Test : Person  //报错:提示不能继承密封类
{

}

22、重写父类的ToString()

  1. 只要是对象,直接ToString打印的话都是命名空间
  2. ToString是object的方法
class Program
{
	Mian()
	{
		Person  p = new Person();
		Console.WriteLine(p.ToString());
	}
}

public class Person
{
	//注意:仅仅是重写了Person中的ToString方法	
	public override void ToString()
	{
		return "Hello";
	}
}

23、接口简介

  1. 接口就是一个规范、能力
  2. 声明语句:
    [public] interface I…able { 成员… }
  3. 接口中的成员不允许添加访问修饰符,默认就是public
  4. 不允许写有方法体的函数
  5. 不允许有字段;可以有自动属性,默认自动声明字段,但是不显示

24、接口的特点(1)

  1. 接口特点
    1)、接口是一种规范,只要有一个类继承了接口,这个类就必须实现这个接口中所有的成员
    2)、为了多态,接口不能被实例化;也就是说接口不能new(不能创建对象
    3)、接口中的成员不能加“访问修饰符”,接口中的成员访问修饰符默认为-public,不能修改
    4)、接口中的成员不能有任何实现(“光说不做”,只是定义了一组未实现的成员)
    5)、接口中只能有方法、属性、索引器、事件,不能有 -字段- ,-构造函数-
    6)、接口与接口之间可以继承,并且可以多继承
    7)、接口并不能去继承一个类,而类可以继承接口 (接口只能继承于接口,而类既可以继承接口,也可以继承类)
    8)、实现接口的子类必须实现该接口的全部成员
    9)、一个类可以同时继承一个类并实现多个接口,如果一个子类同时继承了父类A,并实习了接口IA,那么语法上A必须写在IA的前面
    10)、class MyClass:A,IA( ) ,因为类是单继承
    11)、显示实现接口的目的,解决方法的重名问题
    什么时候显示的去实现接口:当继承的接口中的方法和参数一模一样的时候,用显示的实现接口
    12)、当一个抽象类实现接口的时候,需要子类去实现接口
class Program
    {
        static void Main(string[] args)
        {
            IFlyable f = new Person();
            f.Fly();
            Console.ReadKey();
        }

    }

    public class Bird : IFlyable 
    {
        public void Fly() 
        {
            Console.WriteLine("鸟在飞");
        }
    }
    public class Person : IFlyable 
    {
        public void Fly() 
        {
            Console.WriteLine("人在飞");
        }
    }
    public interface IFlyable 
    {
        void Fly();
    }
public interface M1
{
	void Test1();
}
public interface M2
{
	void Test2();
}
public interface M3
{
	void Test3();
}
public interface SuperM:M1,M2,M3
{
}
public class Person:SuperM
{
	public void M1()
	{
		Console.WriteLine();
	}
	public void M2()
	{
		Console.WriteLine();
	}
	public void M3()
	{
		Console.WriteLine();
	}	
}

25、接口的特点(2)

26、显示实现接口

  1. 显示实现接口就是为了解决方法的重名问题
    class Program
    {
        static void Main(string[] args)
        {
            IFlyable fly = new Bird();
            //调用是接口的Fly()
            fly.Fly();
            Bird bd = new Bird();
            //调用自己的Fly()
            bd.Fly();
            Console.ReadKey();
        }

    }

    public class Bird : IFlyable 
    {
        public void Fly() 
        {
            Console.WriteLine("会飞");
        }
        //这就是显示实现接口
        void IFlyable.Fly() 
        {
            Console.WriteLine("这是接口的飞");
        }
    }
    public interface IFlyable 
    {
        void Fly();
    }

27、接口的小练习

    class Program
    {
        static void Main(string[] args)
        {
            ISwiming iw = new RealDusk();
            iw.Swiming();
            Console.ReadKey();
        }

    }

    public interface ISwiming
    {
        void Swiming();
    }
    public class RealDusk : ISwiming
    {
        public void Swiming()
        {
            Console.WriteLine("真的鸭子用脚游泳");
        }
    }
    public class XPDusk : ISwiming
    {
        public void Swiming()
        {
            Console.WriteLine("橡皮鸭子漂浮游泳");
        }
    }
    public class MTDusk : ISwiming
    {
        public void Swiming() 
        {
            Console.WriteLine("木头鸭子不能游泳");
        }
    }

28、超市收银系统

class Program
    {
        static void Main(string[] args)
        {
            //创建超市对象
            SuperMarket sm = new SuperMarket();
            //展示货物
            sm.ShowPros();
            //跟用户交互
            sm.AskBuying();
            Console.ReadKey();
        }
    }
class ProductFather
    {
        string _name;
        double _price;
        string _id;

        public string Name { get => _name; set => _name = value; }
        public double Price { get => _price; set => _price = value; }
        public string Id { get => _id; set => _id = value; }

        public ProductFather(string name,double price,string id) 
        {
            this.Name = name;
            this.Price = price;
            this.Id = id;
        }
    }
    
class Acer:ProductFather
    {
        public Acer(string name,double price,string id)
            :base(name,price,id)
        {

        }
    }
    
class Banana:ProductFather
    {
        public Banana(string name,double price,string id)
            :base(name,price,id) 
        {
        }
    }
    
class SanSung:ProductFather
    {
        public SanSung(string name,double price,string id)
            :base(name,price,id) 
        {
        }
    }

class JianYou:ProductFather
    {
        public JianYou(string name,double price,string id)
            :base(name,price,id)
        {

        }
    }

class CanKu
    {
        List<List<ProductFather>> list = new List<List<ProductFather>>();

        /// <summary>
        /// 展示货物
        /// </summary>
        public void ShowPros()
        {
            foreach (var item in list)
            {
                Console.WriteLine("我们仓库有{0},价格是{1}元,有{2}个", item[0].Name, item[0].Price, item.Count); //item:货架  item[0]:货架上第一个商品 //item
            }
        }
        public CanKu()
        {
            list.Add(new List<ProductFather>());
            list.Add(new List<ProductFather>());
            list.Add(new List<ProductFather>());
            list.Add(new List<ProductFather>());
        }
        /// <summary>
        /// 进货
        /// </summary>
        /// <param name="type"></param>
        /// <param name="count"></param>
        public void GetPros(string type, int count)
        {
            for (int i = 0; i < count; i++)
            {
                switch (type)
                {
                    case "Acer":
                        list[0].Add(new Acer("红星笔记本", 7999, Guid.NewGuid().ToString()));
                        break;
                    case "Banana":
                        list[1].Add(new Banana("香蕉", 15, Guid.NewGuid().ToString()));
                        break;
                    case "JianYou":
                        list[2].Add(new JianYou("海天酱油", 30, Guid.NewGuid().ToString()));
                        break;
                    case "SanSung":
                        list[3].Add(new SanSung("三星手机", 3000, Guid.NewGuid().ToString()));
                        break;
                }
            }
        }
        /// <summary>
        /// 取货
        /// </summary>
        /// <param name="type"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        #region
        public ProductFather[] QuPros(string type, int count)
        {
            ProductFather[] pros = new ProductFather[count];
            for (int i = 0; i < pros.Length; i++)
            {
                switch (type)
                {
                    case "Acer":
                        //第一个[0]表示第一个货架,第二个[0]表示第一个商品
                        pros[i] = list[0][0];
                        list[0].RemoveAt(0);
                        break;
                    case "Banana":
                        pros[i] = list[1][0];
                        list[1].RemoveAt(0);
                        break;
                    case "JianYou":
                        pros[i] = list[2][0];
                        list[2].RemoveAt(0);
                        break;
                    case "SanSung":
                        pros[i] = list[3][0];
                        list[3].RemoveAt(0);
                        break;

                }
            }
            return pros;
        }
        #endregion
    }

class SuperMarket
    {
        //创建仓库对象后,自动调用仓库中的构建函数,创建四个货架
        CanKu ck = new CanKu();
        //创建超市对象的时候,给仓库的货架上导入货物
        public SuperMarket()
        {
            ck.GetPros("Acer", 1000);
            ck.GetPros("Banana", 1000);
            ck.GetPros("JianYou", 1000);
            ck.GetPros("SanSung", 1000);
        }

        public void AskBuying()
        {
            Console.WriteLine("欢迎光临,请问您需要些什么");
            Console.WriteLine("我们有 Acer、JianYou、Banana、SanSung");
            string type = Console.ReadLine();
            Console.WriteLine("你需要多少");
            int count = Convert.ToInt32(Console.ReadLine());
            //去仓库取货
            ProductFather[] pros = ck.QuPros(type, count);
            //计算价钱
            double Money = GetMoney(pros);
            Console.WriteLine("您总共需要付{0}元",Money);
            Console.WriteLine("请选择你的打折方式 1--不打折 2--打九折 3--打85折 4--买300送50 5--买500送100");
            string input = Console.ReadLine();
            //通过简单工厂的设计模式根据用户的输入获得一个打折对象
            CalFather cal = GetCal(input);
            double calMoney = cal.GetTotalMoney(Money);
            Console.WriteLine("打完折后应付{0}元",calMoney);

        }

        //
        public CalFather GetCal(string input) 
        {
            CalFather cal = null;
            switch (input) 
            {
                case "1":
                    cal = new CalNormal();
                    break;
                case "2":
                    cal = new CalRate(0.9);
                    break;
                case "3":
                    cal = new CalRate(0.85);
                    break;
                case "4":
                    cal = new CalMN(300,50);
                    break;
                case "5":
                    cal = new CalMN(500,100);
                    break;
            }
            return cal;
        }

        public double GetMoney(ProductFather[] pros)
        {
            double Money = 0;
            for (int i = 0; i < pros.Length; i++)
            {
                Money += pros[i].Price;
            }
            return Money;
        }

        public void ShowPros() 
        {
            ck.ShowPros();
        }
    }

/// <summary>
    /// 打折的父类
    /// </summary>
abstract class CalFather
    {
        /// <summary>
        /// 计算打折后的钱
        /// </summary>
        /// <param name="Money">原价</param>
        /// <returns></returns>
        public abstract double GetTotalMoney(double Money);
    }

/// <summary>
    /// 不打折类
    /// </summary>
class CalNormal : CalFather
    {
        //返回原价
        public override double GetTotalMoney(double Money)
        {
            return Money;
        }
    }

class CalRate:CalFather
    {
        private double _rate;

        public double Rate { get => _rate; set => _rate = value; }

        public CalRate(double rate) 
        {
            this.Rate = _rate;
        }

        public override double GetTotalMoney(double Money)
        {
            return Money * this.Rate;
        }
    }

class CalMN : CalFather
    {
        private double _m;
        private double _n;

        public double M { get => _m; set => _m = value; }
        public double N { get => _n; set => _n = value; }

        public CalMN(double m, double n)
        {
            this.M = m;
            this.N = n;
        }
        public override double GetTotalMoney(double Money)
        {
            if (Money >= this.M)
            {
                return Money - ((int)(Money / this.M)) * this.N;
            }
            else 
            {
                return Money;
            }
        }
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值