C# 接口_索引器_命名空间

接口

接口的设计目的是为了定义一组公共的、可被多个类实现的方法和属性
  1. 接口中只能定义属性,不能定义字段,方法不能有方法体

  2. 不能包含静态成员

  3. 接口的成员不能用修饰符,所有成员默认为public,即使是public也不能写

  4. 类或者结构体实现的时候,类的成员相对于接口成员,只能多,不能少,如果接口中规定的属性拥有get和set,类中必须都有,接口规定只有get,类中可以有get和set

  5. 当类实现多个接口的时候,使用,分割

  6. 当类同时继承基类和接口的时候,必须把基类放在前面

     代码示例
    
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _02_接口
{
    internal class Program
    {
        static void Main(string[] args)
        {

            //接口是指一组成员,而不对他们的成员进行实现的引用类型,只能被类和结构体所实现,
            类和结构体继承这个接口的时候,必须实现接口中定义的所有的成员



            //接口只是一种规范,不具备存储数据和定义方法的能力
            //类和结构体实现这个接口的时候,以这个接口的规范为准,进行一一实现,具体怎么实现,
            还是由类和结构体决定
            
            //接口:指定规则,应该有什么
            //类和结构体:实现接口指定的规则,具体怎么有


        }
    }
        //定义一个接口 接口的名字一般以I开头
        //格式:interface 接口的名称{成员}
    interface IBook { 

            //属性
            string Name { get; set; }
            double Price { get; set; }
            void Fn();
            void Fn(string v);

     }

    interface IPaper
    {
        string Type { get; set; }
        string Color { get; set; }
        double Height { get;set; }
    }

    //让某个类实现这个接口,某个类或者结构体实现了这个接口的时候,必须实现这个接口的所有的成员
    //一个类可以使用,实现多个接口
    class Book : IBook, IPaper
    {
        public string Name { get; set; }
        public double Price { get; set; }
        public string Color { get; set; }
        public string Type { get; set; }
        //实现的类总可以拥有更多的成员,但是不能少
        private double price;
        public double Height { get; set; }
        public void Fn() { }
        public void Fn(string v) { }

    }


    interface IPeople
    {
        string Name { get; set; }
        char Sex { get; set; }
        int Age { get; set; }




    }
    interface IStudent
    {
        string StudentNo { get; set; }
        double Age { get; set; }
    }
    class People : IPeople
    {
        public string Name { get; set; }
        public char Sex { get; set; }
        public int Age { get; set; }
    }

    class Student : People, IStudent
    {
        public string StudentNo { get; set; }
        //当基类拥有和接口中同名的属性的时候,派生类不需要自己实现,也可以使用new关键字重新实现(了解);
        public  new double Age { get; set; }
        public void Study()
        {
            Console.WriteLine("我爱学习");
        }
    }



    }



多接口

  1. 当一个类实现的多个接口中拥有相同的类型和相同的属性,只实现一个即可
  2. 当一个类实现的多个接口中拥有不同类型的相同属性,需要使用显示接口实现
  3. 显示接口的实现,不需要也不能加访问修饰符,这个成员访问需要将对象标识为对应的接口的类型
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _03_多接口
{
    internal class Program
    {
        static void Main(string[] args)
        {
           




        }

    }

    interface IA
    {
        string A { get; set; }
        string B { get; set; }
        int D { get; set;}
        void Fn(int v);
    }


    interface IB
    {
       
        string B { get; set; }
        string C { get; set; }
        string D { get;set; }
        void Fn(string v);
    }

    //类可以实现多个接口
    class Tset : IA, IB
    {
        public string A { get; set; }
        //当一个类实现的多个接口中拥有相同的类型和相同的属性,只实现一个即可
        public string B { get; set; }
        

        //当一个类实现的多个接口中拥有不同类型的相同属性,需要使用显示接口实现
        //显示接口的实现,不需要也不能加访问修饰符,这个成员访问需要将对象标识为对应的接口的类型
        int IA.D { get; set; }
        string IB.D { get; set; }
        public bool D { get; set; } 

        //因为方法可以重载,所以可以直接重载两个接口的方法
        public void  Fn(int v) { }
        public void Fn(string v) { }
    }


}

接口的继承

  1. 一个接口可以继承另一个接口,如果接口B继承了接口A,某个类实现了接口B的时候,要实现A和B的所有的成员
  2. 抽象类和接口有什么异同?
  • 相同点:

  • 1.抽象类和接口都不能实例化 不能new

  • 2.都可以包含未实现的方法,由派生类去实现

  • 不同点:

  • 1.抽象类可以包含非抽象成员 接口只能包含抽象成员(这里的抽象可以理解无实现)

  • 2.抽象类只能被实现一个 而接口可以被实现多个(多个接口用逗号隔开·)

  • 3.抽象类的派生类需要使用override去覆写抽象类的抽象成员 接口派生类直接覆写

  • 4.抽象类可以包含访问修饰符 接口不能有访问修饰符

  • 5.抽象类可以包含属性 字段 方法(只能是抽象方法) 接口只能包含属性和方法(不能有抽象方法)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _04_接口的继承
{
    internal class Program
    {
        static void Main(string[] args)
        {

        }
    }
    interface IPeople
    {
        string Name { get; set; }
        int Age { get; set; }
    }

    //一个接口可以继承另一个接口,如果接口B继承了接口A,某个类实现了接口B的时候,要实现A和B的所有的成员
    interface IStudent : IPeople
    {
        string StudentId { get; set;}
       void Study();

    }


    class Student : IStudent
    {
        public string StudentId { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
        public string Name { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
        public int Age { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }

        public void Study()
        {
            throw new NotImplementedException();
        }
    }


}

索引器

索引器: 一种可以让我们使用 “索引” 来访问对象的一种方式

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _05_索引器
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //索引器: 一种可以让我们使用 "索引" 来访问对象的一种方式

           ClassRoom room = new ClassRoom();
           room.Add(new Student() { Name = "吴亦凡", Sex = "男" });
           room.Add(new Student() { Name = "罗志祥", Sex = "男" });
           room.Add(new Student() { Name = "李云迪", Sex = "女" });
           room.Add(new Student() { Name = "郑爽", Sex = "女" });


            //需求:想访问数组中的数据一样,通过索引获取班级中学生的姓名

            Console.WriteLine(room[0].Name); 
            Console.WriteLine(room[1].Name);
            //通过索引这是值,将会执行索引器中的set代码块
            room[3]=new Student() { Name="李易峰",Sex="男"};


            Student s = room["吴亦凡"];//返回Name属性为吴亦凡的那个对象


        }
    }
    class Student
    {
        public string Name { get; set; }
        public string Sex { get; set; }

    }
    class ClassRoom
    {
        public string No { get; set; }
        public string Name { get; set; }

        private List<Student> student =new List<Student>();
        public void Add(Student s)
        {
            student.Add(s);
        }

        //给类中添加一个索引器,这个类的实例就可以想数组一样通过索引进行访问了
        //格式:public 返回值类型 this[索引的类型 索引] {}
        public Student this[int index]
        {
            //通过索引来访问数据的时候执行
            get
            {
                //当前访问的索引
                Console.WriteLine(index);

                return student[index];
            }
            //通过索引来设置这个数据的时候执行(如果没有set代码块,表示这个索引器是只读)
            set
            {
                student[index] = value;
            }


        }
        public Student this[string index]
        {
            get
            {
                //根据传入的值,也就是学生的姓名进行对象的查找
                //for (int i = 0; i < student.Count; i++)
                //{
                //    if (student[i].Name==index)
                //    {
                //        return student[i]; 
                //    }
                //}
                //return null;

                return student.Find(student => student.Name == index);
            }
        }
    }
}

索引器练习

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _06_索引器练习
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Student student =new Student(new string[] {"吴凡","罗祥","李迪"});
            Console.WriteLine(student.Name);
            Console.WriteLine(student[0]);
            Console.WriteLine(student[1]);


            student[3] = "郑";
            Console.WriteLine(student[3]);
        }
    }
    class Student
    {
        // 存储所有学生的名字
        string[] names;
        //Name 设置默认值 为第一个学生的名字
        public string Name { get => names[0]; }
        public Student(string[] names) { 

            this.names = names;
        }

        public string this[int index] {

            //get
            //{
            //    return names[index];
            //}
            get => names[index];
            set
            {
                if (index>=Name.Length)
                {
                    string[] NewNames=new string[index+1];
                    Array.Copy(names, NewNames, names.Length);
                    NewNames[index] = value;
                    names = NewNames;
                }
                else
                {
                    names[index]=value;
                }

            }
        
        }




    }
}

命名空间

  1. 我们的代码越来越多,类越来越多,代码写在同一个文件夹中会导致某个文件结构复杂,代码格式杂乱.命名空间可以让我们在不同的文件中书写代码,不同的文件互相引用
  2. namespace 用来定义一个命名空间 命名空间以大驼峰命名法命名
  3. 如果出现多个命名空间下拥有相同的成员,我们使用的时候会导致不明确的指向
  4. 可以使用 重命名的方案会进行处理
    using myCar1 = Car1.Car;
    using myCar2 = Car2.Car;


//using 命名空间的名称  引用其他的命名空间
using fanfan;

using luozhixiang.xiangxiang;

//如果出现多个命名空间下拥有相同的成员,我们使用的时候会导致不明确的指向
//可以使用 重命名的方案会进行处理
using myCar1 =  Car1.Car;
using myCar2 =  Car2.Car;

//namespace 用来定义一个命名空间 命名空间以大驼峰命名法命名
//格式:namespace 命名空间的名称

//我们的代码越来越多,类越来越多,代码写在同一个文件夹中会导致某个文件结构复杂,代码格式杂乱
//命名空间可以让我们在不同的文件中书写代码,不同的文件互相引用
namespace _07_命名空间
{
    internal class Program
    {
        static void Main(string[] args)
        {
            System.Console.WriteLine("控制台打印");



            //在同一个项目的不同文件中,可以直接访问相同命名空间下的其他类
            People people = new People();
            Student student = new Student();


            //当某个类和当前类不再同一个命名空间下的时候
            //使用 命名空间.目标名称 来引用

            fanfan.Book book1 = new fanfan.Book();

            //我们如果频繁使用其他命名空间的类,结构体 接口等,需要using关键字引用
            //使用using引用之后,就可以把它内部的成员当做相同命名空间下的成员来使用了
            fanfan.Book book2 = new fanfan.Book();
            Book book3 =new Book();

            luozhixiang.xiangxiang.C c = new luozhixiang.xiangxiang.C();

            C c2 = new C();

            luozhixiang.Tool.Test.AA.A a=new luozhixiang.Tool.Test.AA.A();

            Car1.Car cc1 =new Car1.Car();
            Car2.Car cc2 = new Car2.Car();

            myCar1 my1=new myCar1();
        }
    }
}

引用静态类

静态成员可以在using static 引入之后 直接访问
非静态成员 使用实例进行访问


//using xxx 只能引入命名空间 System.Console 不是命名空间 而是一个类 所以不能被引用
//using System.Console;


//我们可以使用using static 引用类, 就可以直接使用类中的静态成员了

using  static System.Console;
using static fanfan.Test;
using fanfan;

namespace _08_引用静态类
{
    internal class Program
    {
        static void Main(string[] args)
        {
            WriteLine("控制台打印");
            WriteLine("控制台打印");

            //静态成员可以在using static 引入之后 直接访问
            Fn1();
            //非静态成员 使用实例进行访问
           new Test().Fn2();
        }
    }
}

引用其他项目

引用同一解决方案下的其他项目

​ 1.当前项目中的"引用"上,右键点击

​ 2.在弹出的菜单中选择添加引用

​ 3.选择 “项目” ==> “解决方案”

​ 4.勾选需要引用的项目

​ 5.点击确定

​ 6.根据对应的项目的命名空间进行引用

引用其他解决方案的项目

​ 1.当前项目中的"引用"上,右键点击

​ 2.在弹出的菜单中选择"添加引用"

​ 3.选择"项目"==>“解决方案”

​ 4.点击"浏览"

​ 5.找到对应解决方案中对应的项目文件 “解决方案目录”–> 项目目录–>bin -->Debug —>Next.x —> xxx.dll或者 xxx.exe

​ 6.点击确定

​ 7.根据对应项目的命名空间进行引用

上期习题答案

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _01_昨天作业
{
    internal class Program
    {
        static void Main(string[] args)
        {
        }
    }
    class Animal
    {
        //Name、MaxAge(最大寿命)、NowAge(当前的年龄,生成对象时随机设置)、Sex
        public string Name { get; set; }
        public int MaxAge { get; set; }
        private int nowAge;
        public int NowAge
        {
            get => nowAge;
            set
            {
                if (value > MaxAge)
                {
                    throw new Exception("年龄超出最大年龄限制");
                }
                nowAge = value;
            }
        }
        public char Sex { get; set; }
        // 一个随机对象,根据最大年龄设置当前年龄
        Random random = new Random();

        public Animal(int maxAge)
        {
            MaxAge = maxAge;
            // 在构造方法中进行年龄的初始化
            NowAge = random.Next(maxAge + 1);
        }
    }
    class Dog : Animal
    {
        // 指定一个无参的构造,当没有传递参数时指定MaxAge为34
        public Dog() : base(34) { }
        // 一个有参的构造,当传递参数时指定MaxAge为传递的值
        public Dog(int maxAge) : base(maxAge) { }

        public void Speak()
        {
            Console.WriteLine("汪汪汪");
        }
    }
    class Cat : Animal
    {
        // 指定一个无参的构造,当没有传递参数时指定MaxAge为39
        public Cat() : base(39) { }
        // 一个有参的构造,当传递参数时指定MaxAge为传递的值
        public Cat(int maxAge) : base(maxAge) { }

        public void Speak()
        {
            Console.WriteLine("喵喵喵");
        }
    }
    class Area
    {
        /// <summary>
        /// 计算矩形的面积
        /// </summary>
        /// <param name="lenght">长</param>
        /// <param name="width">宽</param>
        /// <returns>矩形的面积</returns>
        public static int GetArea(int lenght, int width)
        {
            return lenght * width;
        }

        /// <summary>
        /// 计算正方形的编辑
        /// </summary>
        /// <param name="lenght">边长</param>
        /// <returns>正方形的面积</returns>
        public static int GetArea(int lenght)
        {
            return lenght * lenght;
        }
        /// <summary>
        /// 计算梯形的面积
        /// </summary>
        /// <param name="top">上底长度</param>
        /// <param name="botoom">下底的长度</param>
        /// <param name="h">高度</param>
        /// <returns></returns>
        public static int GetArea(int top, int botoom, int h)
        {
            return (top + botoom) * h / 2;
        }
    }
    //抽象学生类
    abstract class Student
    {
        public abstract int Authority();
    }
    //本科生
    class Undergraduate : Student
    {
        public override int Authority()
        {
            return 5;
        }
    }

    //硕士生
    class Postgraduate : Student
    {
        public override int Authority()
        {
            return 10;
        }
    }
    //博士生
    class Doctor : Student
    {
        public override int Authority()
        {
            return 15;
        }
    }
    abstract class Pay
    {
        public string Id { get; set; }//账号
        public string Pws { get; set; }//密码
        public abstract void payment(double v);//支付的方法,应该接收金额
        public abstract void payment(double v, string account);//支付的方法,应该接收金额
    }
    class WeiXinPay : Pay
    {
        public override void payment(double v)
        {
            Console.WriteLine($"使用微信支付{v}圆,账号是{Id},密码{Pws}");
        }
        public override void payment(double v, string account)
        {
            Console.WriteLine($"使用微信支付给{account}{v}元,账号是{Id},密码{Pws}");
        }

    }
    class AliPay : Pay
    {
        public override void payment(double v)
        {
            Console.WriteLine($"使用支付宝支付{v}圆,账号是{Id},密码{Pws}");
        }
        public override void payment(double v, string account)
        {
            Console.WriteLine($"使用支付宝支付给{account}{v}元,账号是{Id},密码{Pws}");
        }

    }
}

本期习题

  1. 创建一个用于存储某公司员工信息的类Employee,并且可以通过索引来访问员工的姓名和年龄。(提示:使用字典)

    Employee employee = new Employee();

                employee[22] = "fanfan";   // 员工年龄22,名字 fanfan
                employee[22]  = "luoluo"; // 员工年龄22,名字 luoluo
                employee[23] = "Bob";  员工年龄23,名字 Bob
                employee["aa"] = 25;
                employee["Bob"] = 29; //修改Bob的年龄为29
    
  2. 创建一个名为DictionaryWrapper的类,它包装了一个Dictionary对象,并提供了一个索引器,允许我们通过键的部分名称来访问字典中的值。(提示,索引器可以接收多个参数)
    DictionaryWrapper dictionaryWrapper = new DictionaryWrapper();

    // 设置字典中的键值对
    dictionaryWrapper["dog"] = "狗";
    dictionaryWrapper["cat"] = "猫";
    dictionaryWrapper["elephant"] = "大象";
    dictionaryWrapper["dolphin"] = "海豚";
    
    // 输出字典中的值
    Console.WriteLine("通过完整键访问:");
    Console.WriteLine("dog的值是:" + dictionaryWrapper["dog"]);    // 狗
    Console.WriteLine("cat的值是:" + dictionaryWrapper["cat"]);    // 猫
    Console.WriteLine("elephant的值是:" + dictionaryWrapper["elephant"]);  // 大象
    Console.WriteLine("dolphin的值是:" + dictionaryWrapper["dolphin"]);    // 海豚
    
    Console.WriteLine("\n通过键的部分名称访问:");
    Console.WriteLine("以\"do\"开头的键的第一个值是:" + dictionaryWrapper["do", 0]);   // 狗
    Console.WriteLine("以\"do\"开头的键的第二个值是:" + dictionaryWrapper["do", 1]);   // 海豚
    
  3. 将练习1中的类在其他的项目中使用

  4. 将练习2中的类提取到另一个解决方案,并在当前项目中使用

  • 52
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值