C#基础学习笔记(十二)

该博客是C#基础学习笔记,涵盖访问修饰符,如public、private等;介绍设计模式及简单工厂设计模式;讲解值类型和引用类型传值、序列化和反序列化;还涉及部分类、密封类、重写方法、接口等知识,包括接口语法、特点及显示实现接口等。

C#基础学习笔记(十二)

0、复习

class Program
{
    static void Main(string[] args)
    {
        /*泛型集合
            * List<T>,避免装箱 拆箱
            * Dictonary<T,T>
            * 装箱和拆箱
            * 装箱:将值类型转换为引用类型
            * 拆箱:将引用类型转换为值类型
            * 我们应该避免在代码中发生装箱
            * 文件流
            * FileStream StreamReader和StreamWriter
            * 多态:虚方法,抽象类,接口
            * 虚方法:
            * 抽象类:
            */ 
        #region 字典
        List<int> list = new List<int>();
        Dictionary<int, string> dic = new Dictionary<int, string>();
        //添加相同的键时候,会抛异常
        dic.Add(1, "张三");
        //会覆盖
        dic[2] = "李四";
        foreach (KeyValuePair<int, string> kv in dic)
        {
            Console.WriteLine("{0}---{1}", kv.Key, kv.Value);
        }
        #endregion
 
        //File FileStream(操作字节) StreamReader和StreamWriter
 
        #region 写入读取
        //读一个文件
        //自动回收数据using
        using (FileStream fsRead = new FileStream("file.txt", FileMode.OpenOrCreate, FileAccess.Read))
        {
            byte[] buffer = new byte[1024 * 1024 * 5];
            //本次读取实际读取到的字节数
            int r = fsRead.Read(buffer, 0, buffer.Length);
 
            //将字节数组中的每个元素按照我们指定的编码格式解析或字符串
            string s = Encoding.UTF8.GetString(buffer, 0, r);
            Console.WriteLine(s);
        }
 
        //写入一个文件
        using (FileStream fsWrite = new FileStream(@"H:\C#\peixun\Day13\基础班十三天\01复习\bin\Debug\write.txt", FileMode.Append, FileAccess.Write))
        {
            //再写会把之前的覆盖
            //想要追加的话改FileMode.Append
            string s = "欧力给";
            byte[] buffer = Encoding.Default.GetBytes(s);
            fsWrite.Write(buffer, 0, buffer.Length);
        }
        Console.WriteLine("OK");
        #endregion
 
        #region 虚方法和抽象类
        //虚方法和抽象类
        //老师可以起立 学生也可以起立 校长也可以起立
 
        //声明父类去指定子类对象
        Person p = new Student();
        p.StandUp(); 
        #endregion
 
        Console.ReadKey();
    }
 
    public abstract class Person
    {
        public abstract void StandUp();
    }
    public class Student : Person
    {
        public override void StandUp()
        {
            Console.WriteLine("学生起立,说老师好");
        }
    }
    public class Teacher : Person
    {
        public override void StandUp()
        {
            Console.WriteLine("老师起立,说校长好");
        }
    }
    public class HeadMaster : Person
    {
        public override void StandUp()
        {
            Console.WriteLine("校长起来说领导好");
        }
    }
}

1、C#中的访问修饰符

  • public :公开的公共的
  • private:私有的,只能在当前类的内部访问
  • protected:受保护的,只能在当前类的内部以及该类的子类中访问。
  • internal:只能在当前项目中访问。在同一个项目中,internal和public的权限是一样。
  • protected internal:protected+internal

1)、能够修饰类的访问修饰符只有两个:public、internal。

2)、可访问性不一致。

  • 子类的访问权限不能高于父类的访问权限,会暴漏父类的成员。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace _02访问修饰符
{
    class Program
    {
        static void Main(string[] args)
        {
            Person p = new Person();
        }
    }
    //public、internal只能修饰class
    //internal:只能在当前项目中访问
    //在同一个项目中,internal和public的权限是一样
    //private:私有的,只能在当前类的内部访问
    //protected:受保护的,只能在当前类的内部以及该类的子类中访问。
 
    //internal class Person
    //{
    //    //在当前类的内部以及该类的子类中访问
    //    protected string _name;
    //}
    //这样就不行,子类的访问权限不能比父类高,会暴露父类的对象
    //public class Student : Person
    //{
 
    //}
    public class Person
    {
        protected string _name;
        public int _age;
        private char _gender;
        internal int _chinese;
        protected internal int _math;
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using _02访问修饰符;
 
namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            //Student s = new Student();
            ////internal具有保护级
            //Person p = new Person();
        }
        //public class Test : Student
        //{
        //    public void M()
        //    {
        //        _name
        //    }
        //}
    }
}

2、设计模式

设计这个项目的一种方式。

模式就是得到很好研究的范例

走为上,围魏救赵,声东击西

  • 设计模式是软件开发过程中经验的积累特定问题的经过实践检验的特定解决方法

3、简单工厂设计模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xSGN9dvG-1606906956807)(D:\PC\LeetCode\C#基础学习笔记(十二).assets\clip_image001.png)]

分析:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BQPcOcHH-1606906956811)(D:\PC\LeetCode\C#基础学习笔记(十二).assets\clip_image001-1606906380353.png)]

namespace _03简单工厂设计模式

{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("请输入您想要的笔记本品牌");
            string brand = Console.ReadLine();
            NoteBook nb = GetNoteBook(brand);
            nb.SayHello();
            Console.ReadKey();
        }
        /// <summary>
        /// 简单工厂的核心 根据用户的输入创建对象赋值给父类
        /// </summary>
        /// <param name="brand"></param>
        /// <returns></returns>
        //不知道具体要什么,但是返回父类就没错
        public static NoteBook GetNoteBook(string brand)
        {
            NoteBook nb = null;
            //进行多条件的定值判断
            switch (brand)
            {
                case "Lenovo":
                    nb = new Lenovo();
                    break;
                case "Dell":
                    nb = new Dell();
                    break;
                case "Acer":
                    nb = new Acer();
                    break;
                case "ASUS":
                    nb = new ASUS();
                    break;
            }
            return nb;
        }
        public abstract class NoteBook
        {
            public abstract void SayHello();
        }
        public class Lenovo : NoteBook
        {
            public override void SayHello()
            {
                Console.WriteLine("我是联想笔记本");
            }
        }
        public class Dell : NoteBook
        {
            public override void SayHello()
            {
                Console.WriteLine("我是戴尔笔记本");
            }
        }
        public class Acer : NoteBook
        {
            public override void SayHello()
            {
                Console.WriteLine("我是鸿基笔记本");
            }
        }
        public class ASUS : NoteBook
        {
            public override void SayHello()
            {
                Console.WriteLine("我是华硕笔记本");
            }
        }
    }
}

4、值类型和引用类型的传值

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

引用类型在复制的时候,传递的是对这个对象的引用。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tgwAta7p-1606906956814)(D:\PC\LeetCode\C#基础学习笔记(十二).assets\clip_image001-1606906421368.png)]

namespace _04值类型和引用类型
{
    class Program
    {
        static void Main(string[] args)
        {
            //值类型: int double char decimal bool enum struct 存在栈上
            //引用类型:string 数组 自定义类 集合 object 接口 存在堆上
 
            //值传递和引用传递
            #region 值类型
            int n1 = 10;
            int n2 = n1;
            n2 = 20;
            Console.WriteLine(n1);
            Console.WriteLine(n2);
            Console.ReadKey();
            #endregion
 
            #region 引用类型
            //他们指向的是一个堆,一个改变另一个跟着改变
            Person p1 = new Person();
            p1.Name = "张三";
            Person p2 = p1;
            p2.Name = "李四"; //p1=李四
 
            p1.Name = "abc"; //p2=abc
 
            Console.WriteLine(p2.Name);
            #endregion
 
            #region 引用类型1
            //和上例一个原理
            Person p = new Person();
            p.Name = "张三";
            Test(p);
            Console.WriteLine(p.Name);  //李四 
            #endregion
 
            #region 引用类型string
            //string类型也是引用类型,因为每给string复制就重新开辟一块空间,不可变性
            string s1 = "张三";
            string s2 = s1;
            s2 = "李四";
            //s1=张三 s2=李四
            Console.WriteLine(s1);
            Console.WriteLine(s2);
            #endregion
 
            #region ref原理
            int number = 10;
            TestTwo(ref number);
            Console.WriteLine(number); 
            #endregion
 
            Console.ReadKey();
        }
 
        //这个没有返回值,添加ref
        //ref可以把一个变量以参数的方式带到一个方法中,把改变过后的时候的值带回来
        //本质就是ref把n和number在栈中的地址变一样了,原来只是把number本身的10给了n,现在把地址给了n
        //这相当于值传递变成引用传递
        //这就相当于这两个是同一块地址
        public static void TestTwo(ref int n)
        {
            n += 10;
        }
 
        //Person pp = p;
        public static void Test(Person pp)
        {
            Person p = pp;
            p.Name = "李四";
        }
    }
    public class Person
    {
        private string _name;
 
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
 
 
    }
}

5、序列化和反序列化

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

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

  • 作用:传输数据。

  • 序列化的过程:

1)、将这个类标记为可以被序列化的。

namespace _05序列化和反序列化
{
    class Program
    {
        static void Main(string[] args)
        {
            #region 模拟发送
            //要将p这个对象 传输给对方电脑
            //在一台电脑上模拟
            //写入就是发送的过程,读取作为接受
            Person p = new Person();
            p.Name = "张三";
            p.Age = 19;
            p.Gender = '男';
            using (FileStream fsWrite = new FileStream(@"D:\PC\C#\peixun\Day13\111.txt", FileMode.OpenOrCreate, FileAccess.Write))
            {
                //开始序列化对象
                BinaryFormatter bf = new BinaryFormatter();
                //第一个需要的是stream而FileStream是他的子类,里氏转换,子类可以父类
                bf.Serialize(fsWrite, p);
            }
            Console.WriteLine("序列化成功");
            #endregion
 
            //接收对方发来的二进制 反序列化成对象
            Person p;
            using (FileStream fsRead = new FileStream(@"D:\PC\C#\peixun\Day13\111.txt", FileMode.OpenOrCreate, FileAccess.Read)) 
            {
                BinaryFormatter bf = new BinaryFormatter();
                p = (Person)bf.Deserialize(fsRead);
            }
            Console.WriteLine(p.Name);
            Console.WriteLine(p.Age);
            Console.WriteLine(p.Gender);
            Console.ReadKey();
        }
    }
    //标记
    [Serializable]
    public class Person
    {
        private string _name;
 
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        private char _gender;
 
        public char Gender
        {
            get { return _gender; }
            set { _gender = value; }
        }
 
        private int _age;
 
        public int Age
        {
            get { return _age; }
            set { _age = value; }
        }
 
    }
}

6、partial部分类

namespace _06部分类
{
    class Program
    {
        static void Main(string[] args)
        {
            //同一个命名空间下不能有两个名字相同的类
            //但是有时候又必须要,在团队开发的时候,几个人都要写相同名字的类
            //用到部分类,前面加partical,这样两个类是一个类
            //上面的东西都可以用
            //但是不能有一样的方法
        }
    }
    public partial class Person
    {
        private string _name;
    }
    public partial class Person
    {
        public void Test()
        {
            _name = "张三";
        }
    }
}

7、sealed密封类

不能够被其他类继承,但是可以继承于其他类。

namespace _07密封类
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }
    //但是密封类可以继承
    public sealed class Person : Test
    {
 
    }
    //密封类不能被继承
    public class Test /*: Person*/
    {
 
    }
}

8、重写ToString()方法

namespace _08重写ToString__方法
{
    class Program
    {
        static void Main(string[] args)
        {
            Person p = new Person();
            //这样打印出来的是对象的命名空间
            //所有的类型都可以tostring,因为他们都是object的子类,而tostring是onject的方法,所以都能用
            Console.WriteLine(p.ToString());
            Console.ReadKey();
        }
    }
    public class Person
    {
        //可以发现有三个函数可以重写,他们是虚方法,子类可以调用父类的虚方法
        //这里只能是Person的类的tostring变成了Hello Word
        public override string ToString()
        {
            return "Hello Word";
        }
    }
}

9、接口

[public] interface I…able

{

成员;

}

namespace _09接口
{
    class Program
    {
        static void Main(string[] args)
        {
            //接口就是一个规范,能力
        }
    }
    public class Person
    {
        public void CHLSS()
        {
            Console.WriteLine("我是人类,我可以吃喝拉撒睡");
        }
    }
    public class CBAPlayer
    {
        public void KouLan()
        {
            Console.WriteLine("我可以扣篮");
        }
    }
    //这时我的学生也想扣篮,这时候就可以使用接口了
    //考虑接口的时候:多继承
    public class Student : Person, IKouLanble
    {
        public void Koulan()
        {
            Console.WriteLine("我也可以扣篮");
        }
    }
    public interface IKouLanble
    {
        void Koulan();
    }
}

10、接口的语法:

  • 接口是一种规范。

  • 只要一个类继承了一个接口,这个类就必须实现这个接口中所有的成员

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

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

  • (默认为public)接口中的成员不能有任何实现(“光说不做”,只是定义了一组未实现的成员)。

  • 接口中只能有方法、属性、索引器、事件,不能有“字段”和构造函数。

  • 接口与接口之间可以继承,并且可以多继承。

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

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

  • 一个类可以同时继承一个类并实现多个接口,如果一个子类同时继承了父类A,并实现了接口IA,那么语法上A必须写在IA的前面。

  • class MyClass:A,IA{},因为类是单继承的。

  • 显示实现接口的目的:解决方法的重名问题

  • 什么时候显示的去实现接口:

当继承的借口中的方法和参数一摸一样的时候,要是用显示的实现接口

当一个抽象类实现接口的时候,需要子类去实现接口。

namespace _10接口的语法特征
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }
    public interface IFlyable
    {
        //接口的成员不允许添加访问修饰符,默认就是public     
        /*public*/ void Fly();
        string Test();
 
        ////在抽象类中可以有方法体,接口中不允许写具有方法体的函数
        //void Test2()
        //{
        //    Console.WriteLine("接口中的方法");
        //}
 
        ////不允许有字段
        //string _name;
 
        //自动属性和普通属性的区别
        //他们本质还是一个方法,和上面一样
        string Name
        {
            get;
            set;
        }
        
    }
}

11、自动属性和普通属性的区别(补充)

public class Person
    {
        private string _name;
 
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        //自动属性
        //没有字段,但是通过反编译器可以看出它还是会给你生成字段,两个本质是一样的
        public int Age
        {
            get;
            set;
        }
    }

12、接口的特点

namespace _12接口的特点
{
    class Program
    {
        static void Main(string[] args)
        {
            //接口不能被实例化
            //不能被实例化的有虚方法,静态类,接口
            //IFlyable fly = new IFlyable();
            IFlyable fly = new Person();
            IFlyable fly1 = new Bird();
            fly.Fly();
            fly1.Fly();
            Console.ReadKey();
        }
    }
    public class Person : IFlyable
    {
        public void Fly()
        {
            Console.WriteLine("人类在飞");
        }
    }
    public class Student : Person, IFlyable
    {
        //如果一个类既继承与类又继承与接口,类要写在接口之前
        public void Fly()
        {
            Console.WriteLine("人类在飞");
        }
    }
 
    public class Bird : IFlyable
    {
        public void Fly()
        {
            Console.WriteLine("鸟在飞");
        }
    }
    public interface IFlyable
    {
        //不允许有访问修饰符 默认public
        //方法、自动属性
        void Fly();
    }
    public interface M1
    {
        void Test1();
    }
    public interface M2
    {
        void Test2();
    }
    public interface M3 /*: Person*/
    {
        //接口只能继承于接口
        void Test3();
    }
    public interface SupperInterface : M1, M2, M3
    {
        //接口里面的成员没有方法体
        //他给子类用
    }
    public class Car : SupperInterface
    {
        public void Test1()
        {
            throw new NotImplementedException();
        }
 
        public void Test2()
        {
            throw new NotImplementedException();
        }
 
        public void Test3()
        {
            throw new NotImplementedException();
        }
    }
}

13、接口练习

namespace _13接口练习
{
    class Program
    {
        static void Main(string[] args)
        {
            //麻雀会飞 鹦鹉会飞 鸵鸟不会飞 企鹅不会飞 直升机会飞
            //需要多态来实现
            //虚方法 抽象类 接口
            IFlyable fly = new YingWu();
            fly.Fly();
            Console.ReadKey();
        }
        public class Bird
        {
            //public void Fly()
            //{
            //    Console.WriteLine("会飞");
            //}
            //public abstract void Fly();
            //public void Fly()
            //{
            //    Console.WriteLine("会飞");
            //}
            public double Wings
            {
                get;
                set;
            }
            public void EatAndDrink()
            {
                Console.WriteLine("我会吃喝");
            }
        }
        public interface IFlyable
        {
            void Fly();
        }
        public interface ISpeak
        {
            void Speark();
        }
        public class MaQue : Bird, IFlyable
        {
            public void Fly()
            {
                Console.WriteLine("麻雀会飞");
            }
        }
        public class YingWu : Bird, IFlyable, ISpeak
        {
            public void Fly()
            {
                Console.WriteLine("鹦鹉会飞");
            }
 
            public void Speark()
            {
                Console.WriteLine("鹦鹉可以学习人说话");
            }
        }
        public class TuoBird : Bird
        {
                
        }
        public class QQ : Bird
        {
 
        }
        public class Plane : IFlyable
        {
            public void Fly()
            {
                Console.WriteLine("直升机会飞");
            }
        }
    }
}

14、显示实现接口

namespace _14显示实现接口
{
    class Program
    {
        static void Main(string[] args)
        {
            //显示实现接口就是为了解决方法的重名问题
            IFlyable fly = new Bird();
            fly.Fly();
            Bird brid = new Bird();
            brid.Fly();
            Console.ReadKey();
 
        }
    }
    public class Bird : IFlyable 
    {
        public void Fly()
        {
            Console.WriteLine("鸟会飞");
        }
        /// <summary>
        /// 接口实现接口
        /// </summary>
        /// 
        void IFlyable.Fly()
        {
            //默认private
            Console.WriteLine("我是接口的飞");
        }    
    }
    public interface IFlyable
    {
        void Fly();
    }
}

15、总结

namespace _15总结
{
    class Program
    {
        static void Main(string[] args)
        {
            //什么时候用虚方法来实现多态?
            //什么时候用抽象类来实现多态?
            //什么时候用接口来实现多态?
            //抽象类
            //在提供的几个类中如果可以抽象出一个父类,并且在父类写上共有的方法,但是不知道怎么写
            //虚方法
            //抽象出一个父类,并且在父类写上共有的方法,可以写,需要创建对象
            //接口
            //找不出父类,但是又有共同的行为
 
            //练习
            //真的鸭子会游泳 木头鸭子不会游泳 橡皮鸭子会游泳
            //用接口 会干什么 侧重能力
            //把真鸭子提出父类 但是不能写游泳的方法 因为木鸭子不会游泳
            //也不能写抽象方法 因为真鸭子需要创建对象
            //虚方法也不行 木鸭子不会游泳
            ISwimming swim = new RealDuck();
            swim.Swim();
            Console.ReadKey();
        }
    }
    public interface ISwimming
    {
        void Swim();
    }
    public class RealDuck : ISwimming
    {
        public void Swim()
        {
            Console.WriteLine("真的鸭子靠脚蹼游泳");
        }
    }
    public class MuDuck
    {
 
    }
    public class XPDuck : ISwimming
    {
        public void Swim()
        {
            Console.WriteLine("橡皮鸭子飘着游泳");
        }
    }
 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值