1.6C#语言基础-类和结构

  • 对象 =算法+数据结构
  • 程序=对象+对象+...
  • 类是属性和方法的集合

类的几点特性

  • 封装:属性和方法的封装

  • 继承:通过继承,继承父类属性和方法,并拓展自身方法和属性

  • 多态:同一方法的不同实现

学习好反射,可以写出很厉害的代码

属性

  • 类的成员,变量
  • 属性不能作为ref或out参数传递
  • get访问器用来获取属性值
  • set访问器用来设置值
  • 通过 对象.属性名 来访问和设置

类的两种形式

  1. 在公共语言运行库的基础库中定义的属性
    将SystemRdflection.TypeAttributes.Serializable用于自定义类,一便使该类中的成员可以序列化
[System.Serializable]
public class MyClass
{}
  1. 自定义属性

get/set访问器使用

public class Date
{
    private int Day=7;
    public int day
    {
        get{return Day;}
        set{
                if(value>0&&value<8)
                   {
                        Day=value;
                    }
            }
    }
}

get访问器必须返回值,类型和属性的类型保持一致,set返回值为void ,使用value隐式参数

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

namespace StudyClass
{

    class MyClass
    {
        private string id = "";
        private string name = "";
        /// <summary>
        /// 定义id属性可读可写
        /// </summary>
        public string ID
        {
            get
            {
                return id;
            }
            set
            {
                id = value;
            }
        }
        /// <summary>
        /// 定义属性name 可读可写
        /// </summary>
        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                name = value;
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {

            //创建一个对象
            MyClass c = new MyClass();
            c.ID = "10001";
            c.Name = "xiaoming";
            Console.WriteLine("id:" + c.ID + "\n" + "name:" + c.Name);
        }
    }
}

类的方法

  • 必须指定修饰符,常用的有4个访问修饰符:private、public、protected、internal,声明修饰符8个:partial,new,static,virtual,override,sealed,abstract,eternal

  • 指定返回值,可有参数

4个访问修饰符

访问修饰符 说明
private 私有模式,只能被自己访问
public 公共模式,访问不受限制
protected 保护模式,类本身和该类的派生类可访问
internal 同一程序集才能访问

8个声明修饰符

声明修饰符 说明
partial 在整个同一程序中定义分部类和结构
new 从基类成员隐藏继承的成员
static 声明属于类本身,不属于特定对象成员
virtual 在派生的类中可以重写的方法或者访问器
override 提供从基类继承的虚拟成员的新实现
sealed 指定类不能被继承
abstract 指定某个类只能式其他类的基类
extern 指示在外部实现的方法

声明方法需要遵循的规则

  • 声明最多包含 static,virtual ,override修饰符中的一个
  • 声明最多包含 new 和 override的一个
  • 使用了abstract,不能再包含static ,virtual,sealed 或extern
  • 使用了private,不能再包含virtual,override,abstract
  • 使用了sealed,不能包含override

静态方法

  • 静态方法不能引用this
  • 静态方法使用static声明
  • 静态方法属于类本身
public static int Add(int x, int y)
{
    return x+y;
}

非静态方法

  • 非静态方法可以通过this来调用

方法重载

方法名称一样,返回值,参数个数、参数类型,参数顺序,只要其中一个不同即可

public static int Add(int x,int y)
{
    return x + y;
}
public double Add(int x,double y)
{
    return x + y;
}
public int Add(int x,int y, int z)
{
    return x + y + z;
}

结构

  • 结构式值类型
  • 用来封装一组相关变量
  • 向方法中传递结构时,结构是通过值传递的方式传递
  • 结构的实例可以不使用new运算符
  • 结构可以声明构造函数,必须带参数才行
  • 结构不能继承,所有的结构都是直接结成System.ValueType,System.ValueType继承Sytem.Object
  • 结构可以实现接口
  • 在结构中初始化实例字段是错误的

由于结构的副本由编译器自动创建和销毁,因此不需要使用默认构造函数和析构函数。实际上编译器通过为所有字段赋予默认值来实现默认构造函数

结构的定义


结构修饰符 struct 结构名
{}
//demo

public struct Rect
{
    public double width;
    public double height;

    public double Area()
    {
        return width*height;
       }
}
static void Main(string[] args)
{
    Rect rect;
    rect.width = 5;
    rect.height = 3;
    Console.WriteLine("面积为:", rect.Area());
}

构造函数 和析构函数

  • 构造函数用来初始化,实例化时调用,构造函数和类命相同
  • 析构函数用来资源回收处理,实例销毁时调用,析构函数在类命前加入~

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

namespace StudyClass
{
    class Program
    {
        public int x = 3;
        public int y = 5;
        public int z = 0;
        public Program()
        {
            z = x + y;//构造函数中初始化z

        }
        ~Program()
        {
            Console.WriteLine("执行了析构函数");
        }
        static void Main(string[] args)
        {
            Program prog = new Program();
            Console.WriteLine(prog.z);
        }
    }
}
//结果输出
8
执行了析构函数

不带参数的钩函数是默认构造函数,一个类中只能有一个析构函数

继承

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

namespace StudyClass
{

    class MyClass1
    {
        private int x = 0;
        private int y = 0;
        public int X
        {
            get { return x; }
            set { x = value; }
        }
        public int Y
        {
            get { return y; }
            set { y = value; }
        }

        public int Add1()
        {
            return X + Y;
        }

    }
    class MyClass2:MyClass1
    {
        private int z= 0;
    
        public int Z
        {
            get { return z; }
            set { z = value; }
        }
      

        public int Add2()
        {
            return X + Y+Z;
        }

    }

    class Program
    {
    
        static void Main(string[] args)
        {
            MyClass1 c1 = new MyClass1();
            MyClass2 c2 = new MyClass2();
            c1.X = 3;
            c1.Y = 5;
            c2.X = 4;
            c2.Y = 6;
            c2.Z = 6;
            Console.WriteLine(c1.Add1());
            Console.WriteLine(c2.Add1());
            Console.WriteLine(c2.Add2());
        }
    }
}
//结果输出
8
10
16
请按任意键继续. . .

在子类中重写基类中的虚方法,可以使用base.方法名调用基类的虚方法

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

namespace StudyClass
{

    class MyClass1
    {
      
        public virtual int Add(int x,int y)
        {
            return x+y;
        }

    }
    class MyClass2:MyClass1
    {
        public int z = 0;
        public int Z
        {
            get { return z; }
            set { z = value; }
        }
        public override int Add(int x, int y)
        {
            return base.Add(x,y)+z;
        }

    }


    class Program
    {
    
        static void Main(string[] args)
        {
            MyClass2 c = new MyClass2();
            c.Z = 5;
            Console.WriteLine(c.Add(4, 6));
        }
    }
}
//结果输出
15
请按任意键继续. . .

多继承需要使用接口,c#只支持单继承,继承的多个接口禁用逗号隔开

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

namespace StudyClass
{

    interface IPeople
    {
        string Name
        {
            get;
            set;
        }
        string Sex
        {
            get;
            set;
        }
    }
    class MyClass
    {
        public void Show()
        {
            Console.WriteLine("个人信息:");
        }
    }



    class Program:MyClass,IPeople
    {
        string name = "";
        string sex = "";
        //继承了接口,必须把接口中访问器完善
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        public string Sex
        {
            get { return sex; }
            set { sex = value; }
        }

    
        static void Main(string[] args)
        {
            Program prog = new Program();
            IPeople ipeople = prog;

            ipeople.Name = "XIAOMING";
            ipeople.Sex = "男";
            prog.Show();
            Console.WriteLine(ipeople.Name + " " + ipeople.Sex);
        }
    }
}

多态

  • 一个接口,多种方法
  • 子类重写基类的虚方法

子类继承基类的所有方法字段,如果想要改变基类的数据和行为,有两种方式:

  • 新的派生成成员替换基类成员,或者重写基类的方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StudyClass
{

    class MyClass1
    {
        private int x = 0;
        private int y = 0;

        public int X
        {
            get
            {
                return x;
            }
            set { x = value; }
        }
        public int Y
        {
            get { return y; }
            set { y = value; }
        }
        public virtual int Add()
        {
            return X + Y;
        }
    }
    class MyClass2:MyClass1
    {
        public override int Add()
        {
            int x=5;
            int y = 7;
            return x + y;
        }
    }

    class Program
    {

        static void Main(string[] args)
        {
            MyClass2 c2 = new MyClass2();
            
            MyClass1 c1 = (MyClass1)c2;
            c1.X = 9;
            c2.Y = 20;

            Console.WriteLine(c2.Add());//调用子类的方法
            Console.WriteLine(c1.Add());//调用子类的方法
        }
    }
}


  • 新的拍成成员替换基类的成员,使用new,如果基类定义了一个方法,字段,这new关键字用于在子类创建该方法字段的新定义
   class MyClass2:MyClass1
    {
        public new int Add()
        {
            int x=5;
            int y = 7;
            return x + y;
        }
    }
posted @ 2018-12-16 12:54  随时静听  阅读(186)  评论(0编辑  收藏  举报