C#面向对象三大特性 更新中

目录

封装

类和对象

成员变量和访问修饰符

成员方法

构造函数和析构函数

成员属性

索引器

静态成员

静态类和静态构造函数

拓展方法

运算符重载

内部类

分布类

继承


封装

类和对象

类一般声明于namespace语句块中,使用帕斯卡命名法,类是引用对象,在同一语句块中类不能重名。用关键字class 基本语法: class 类名{}

类一般有三种声明方式(如代码)

第一种没有赋值

第二种虽然赋值但是为空

第三种就是创建一个新对象(常用)

namespace Lesson01_封装_类和对象
{
    // 类一般声明于namespace语句块中
    // 帕斯卡命名法
    // 类对象是引用类型
    // 在同一语句块中类不能重名
    /// <summary>
    /// 人
    /// </summary>
    class Person
    {
        
    }
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Lesson01_封装_类和对象");
            Person person1;
            Person person2 = null;
            Person person3 = new Person();
        }
    }
}

成员变量和访问修饰符

namespace Lesson02_封装_成员变量和访问修饰符
{
    class Person
    {
        // 特征--成员变量
        public string name;
        public int age = 0;
        // 与结构体不同,类中可以使用自己类型,但不能初始化会导致循环
        public Person father;
        
    }
    /*
     公共和私有与结构体一致
     protected 保护的 只有自己内部和子类才可以使用
     */
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Lesson02_封装_成员变量和访问修饰符");
            Person p = new();
            p.name = "Test";
            Console.WriteLine(p.name);
            /*
            如果类中的变量无初始值,则在new之后会默认分配初始值
            有符号无符号浮点: 0
            bool: false
            char: ''
            引用类型: null
             */
            // 想要获得一个类型的初始值
            // default(类型)
            Console.WriteLine(default(byte)); // 0
        }
    }
}

访问修饰符如下:

1. public 公共的 内外都可以访问

2. private 私有的 只有内部才可以访问

3. protected 保护的 只有内部或子类可以访问

成员变量的格式如下:

访问修饰符 类型 变量名; 

其中访问修饰符可以不写,不写默认为私有的,类型可以是任何类型(包括类和结构体) 

类中的变量可以有默认值 

如果该对象是公共的那么可以用 实例化对象.变量名 来进行使用或者修改

成员方法

namespace Lesson03_封装_成员方法
{
    // 成员方法不用加static
    class Person
    {
        public string name = "小明";
        public int age;
        public Person[] friends;

        /// <summary>
        /// 说话
        /// </summary>
        /// <param name="content">内容</param>
        public void Speak(string content)
        {
            Console.WriteLine(content);
        }
        public void AddFriend(Person p)
        {
            if (friends == null)
            {
                friends = [p];
                if (p.friends == null || !isIn(this, p.friends))
                {  
                    // 将自己成为对方的朋友
                    p.AddFriend(this);
                }
                return;
            }
            Person[] temp = new Person[friends.Length + 1];
            for (int i = 0; i < friends.Length; i++)
            {
                temp[i] = friends[i];
            }
            temp[^ - 1] = p;
            friends = temp;
            if (p.friends == null || !isIn(this, p.friends))
            {
                // 将自己成为对方的朋友
                p.AddFriend(this);
            }
            
        }
        private bool isIn(Person p, Person[] array)
        {
            for (int i = 0; i < array.Length; i++)
            {
                if (p == array[i])
                {
                    return true;
                }
            }
            return false;
        }
        
    }
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Lesson03_封装_成员方法");
            // 只有在实例化后才能调用其内部函数
            Person p = new Person();
            p.name = "Test";
            Console.WriteLine(p.name);
            Person p2 = new Person();
            p2.name = "Test2";
            Console.WriteLine(p2.name);
            Console.WriteLine("-------");

            p2.AddFriend(p);
            for (int i = 0; i < p.friends.Length; i++)
            {
                Console.WriteLine(p.friends[i].name);
            }
        }
    }
}

成员方法的语法如下:

访问修饰符 返回类型 名字(参数列表){}

如果想要实例化对象点出来使用的话则不加static

构造函数和析构函数

namespace Lesson04_封装_构造函数和析构函数
{
    class Person
    {
        public string name;
        public int age;

        private Person()
        {
            name = "Test";
            age = 10;
        }
        // 特殊写法: 访问修饰符 名(参数): this(参数)
        // 先调用this的函数(即自己的构造函数)再执行代码
        public Person(string name, int age): this()
        {
            this.name = name;
            this.age = age;
        }

        // 析构函数
        // 语法: ~类名() {}
        // 当引用类型的堆内存被回收后,将调用此函数
        /*
         垃圾回收(GC)
         用遍历在堆(Heap)分配的内存
         判断引用类型是否被引用并需要
         未被引用的对象就需要被回收

         垃圾回收(GC)只支持堆(Heap)上的回收
         而栈(Stack)是由自己自动分配回收,不需要GC
         */
        ~Person()
        {
            
        }

    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Lesson04_封装_构造函数和析构函数");
            // 如果构造函数中无无参构造函数,则默认的无参构造函数会被顶掉
            Person p = new Person("小明", 20);
            // 手动触发垃圾回收
            GC.Collect();
        }
    }
}

构造函数基本语法如下:

访问修饰符(一般是public) 类名(参数列表){}

构造函数的使用和结构体一致

其余知识点请参考代码

成员属性

namespace Lesson05_成员属性
{
    class Person
    {
        public string name;
        public int age;
        private int money;
        private string smallName;

        /*
         语法:
        访问修饰符 返回类型 名 { get{} set{} }
         */
        // 属性命名使用帕斯卡命名法
        public string Name
        {
            get 
            {
                // 访问Name获取私有变量
                return smallName;
            }
            set 
            {
                // value关键字代表外部赋值的值
                smallName = value;
            }
        }
        public int Money
        {
            // get和set前可以加访问修饰符,不加默认为属性的权限
            // get和set可以只有一个
            get
            {
                return Convert.ToInt32(Convert.ToString(money), 2);
            }
            set
            {
                // 加密操作
                money = int.Parse(Convert.ToString(value < 0 ? 0 : value, 2));
            }
        }
        // 自动属性,类似于声明了一个新的成员变量,并且get和set可以加上访问修饰符
        public bool Sex
        {
            get;
            set;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Lesson05_成员属性");
            Person p = new()
            {
                Name = "小名",
                Money = 5000,
                Sex = false
            };
            Console.WriteLine(p.Name);
            Console.WriteLine(p.Money);
            
        }
    }
}

语法如下:

访问修饰符 类型 属性名(帕斯卡命名法) {get{} set{}}

 或者自动属性:

访问修饰符 类型 自动属性名 {get; set;}

其余参考代码 

索引器

namespace Lesson06_封装_索引器
{
    class Person
    {
        private List<Person> friends = new();
        private int[,] array;
        /*
         语法:
        访问修饰符 返回类型 this[参数列表] { get{} set{} }
         */
        // 索引器也可以重载
        public int this[int i, int j]
        {
            get
            {
                return array[i, j];
            }
            set
            {
                array[i, j] = value;
            }
        }
        public Person this[int i]
        {
            get
            {
                if (friends == null || friends.Count - 1 < i)
                {
                    return null;
                }
                return friends[i];
            }
            set
            {
                
                if (friends == null)
                {
                    friends = new List<Person>(1);
                    friends[0] = value;
                }
                if (i > friends.Count - 1)
                {
                    friends.Add(value);
                    return;
                }
                friends[i] = value;
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Lesson06_封装_索引器");
            Person p = new();
            p[0] = new Person();
            Console.WriteLine(p[0]);
            p[0, 0] = 10;
        }
    }
}

 语法如下:

访问修饰符 返回类型 this[参数列表] { get{} set{} }

其中get和set与成员属性一致

其余参考代码 

静态成员

namespace Lesson07_封装_静态成员
{
    class Test
    {
        // 静态变量
        public static int a = 10;
        // 普通变量
        public int b = 0;

        // const类似于static
        // 也可以点出来使用,但const必须写在访问修饰符之后,static没有位置的限制
        // const只能修饰变量
        public const int c = 10;

        // 静态函数
        public static int CalcInt(int a, int b)
        {
            // 静态方法中不可以调用非静态成员
            return a + b;
        }
        // 普通函数
        public int CalcDoubleNumber(int a)
        {
            // 但是在普通方法中可以调用静态成员
            return a * a;
        }

    }
    
    static class Temp
    {
        public static int Test { get; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Lesson07_封装_静态成员");
            Test t = new();
            // 静态变量属性函数由类名.出来使用
            Console.WriteLine(Test.a);
            Console.WriteLine(Test.CalcInt(10, 3));
        }
    }
}

关键字:  static

其余参考代码

静态类和静态构造函数

namespace Lesson08_封装_静态类和静态构造函数
{
    // 静态类无法被实例化,内部只能有静态成员,类似于一个大工具包
    static class MathsTools
    {
        public const double PI = 3.1415926;
        public static double CalcCircle(int r) { return r * r * PI; }
        public static int Sum(params int[] arr)
        {
            int sum = 0;
            for (int i = 0; i < arr.Length; i++)
            {
                sum += arr[i];
            }
            return sum;
        }
        public static float Sum(float[] array)
        {
            float sum = 0;
            for (int i = 0; i < array.Length; i++)
            {
                sum += array[i];
            }
            return sum;
        }
    }
    static class StaticClass
    {
        public static int a = 100;
        public static int b = 100;
        // 静态构造函数不能加3p或者参数
        // 用于初始化静态成员
        // 只会自动调用一次(前提:调用此类中的成员前)
        static StaticClass()
        {

        }
    }
    class TestClass
    {
        public static int a = 100;
        // 只会自动调用一次(前提:调用此类中的成员前)
        // 非静态和静态不冲突,不算重载
        static TestClass()
        {

        }
        public TestClass()
        {

        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Lesson08_封装_静态类和静态构造函数");
        }
    }
}

参考代码吧 

拓展方法

namespace Lesson09_封装_拓展方法
{
    static class Tools
    {
        // 拓展类可以是自定义的类
        // 访问修饰符 static 返回值 名(this 拓展类名 参数名, 普通参数列表) {}
        // 只能将拓展方法写入静态类中
        // 为int拓展了一个普通成员方法
        // value代表使用该方法的实例化对象
        // 如果拓展方法和为拓展的类名重合,那么只能调用拓展类自带的函数

        /// <summary>
        /// 将int转为二进制
        /// </summary>
        /// <param name="value"></param>
        public static void Binary(ref this int value)
        {
            value = int.Parse(Convert.ToString(value, 2));
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Lesson09_封装_拓展方法");
            int a = 10;
            a.Binary();
            Console.WriteLine(a);            
        }
    }
}

语法如下:

访问修饰符 static 返回值 名(this 拓展类名 参数名, 普通参数列表) {}

其余参考代码...

运算符重载

namespace Lesson10_封装_运算符重载
{
    static class Tools
    {
        public static void GetBaseData(this Test value)
        {
            Console.WriteLine(value.X + "\t" + value.Y);
        }
    }
    class Test
    {
        public int X { get; set; }
        public int Y { get; set; }

        // 语法: public static 返回类型 operator 运算符(参数列表) {}
        // 可以重载,在进行操作之时必须按照参数顺序来
        public static Test operator +(Test t1, Test t2)
        {
            Test t = new()
            {
                X = t1.X + t2.X,
                Y = t1.Y + t2.Y
            };
            return t;
        }
        public static Test operator +(Test t1, int[] arr)
        {
            Test t = new()
            {
                X = t1.X + arr[0],
                Y = t1.Y + arr[1]
            };
            return t;
        }

        /*
        可重载的运算符
            算数运算符:     +  -   *   /   %   ++   --
            逻辑运算符:     !
            位运算符:       &   |  ^  ~  <<  >> 
            条件运算符必须成对出现
            条件运算符:      <  <=  >  >=  ==  != 

        不可重载的 运算符             索引符   强转符   点  赋值  三目运算符
            逻辑运算符 :  &&    ||   [ ]     ()      .   =      ?:
         
         */
    }
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Lesson10_封装_运算符重载");
            Test t1 = new()
            {
                X = 10,
                Y = 20
            };
            Test t2 = new()
            {
                X = 11,
                Y = 21
            };
            Test t3 = t1 + t2;
            t3.GetBaseData();
            // 可以按照顺序连加
            t3 = t1 + [0, 11] + t2;
            t3.GetBaseData();
        }
    }
}

语法: 

语法: public static 返回类型 operator 运算符(参数列表) {}

内部类

非重点,就是类中套类

分布类

namespace Lesson11_封装_内部类和分布类
{
    // 内部类即类中套类
    class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }

        public class Body
        {
            Arm leftArm;
            Arm rightArm;
            public class Arm
            {
                public void CatchThing(string thing)
                {
                    // ...
                }
            }
            public Arm this[string value]
            {
                get
                {
                    switch (value)
                    {
                        case "LeftArm":
                        case "leftArm":
                        case "LEFTARM":
                        case "leftarm":
                            return leftArm;
                        case "RightArm":
                        case "rightArm":
                        case "RIGHTARM":
                        case "rightarm":
                            return rightArm;
                    }
                    return null;
                }
            }
        }
    }

    // 分布类将一个类分多部描述
    // 关键字: partial
    // 成员不能重复

    // 分布方法和分布类大同小异
    // 只能是私有无返回值不能用out可以有参数
    partial class Student
    {
        public string Name { get; set; }
        public int Id { get; set; }

        partial void Study();
    }
    partial class Student
    {
        partial void Study()
        {
            // 逻辑内容...
        }
        public void Speak()
        {

        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Lesson11_封装_内部类和分布类");
            Person p = new();
            Person.Body body = new();

            Student s = new()
            {
                Name = "小明"
            };
            s.Speak();
        }
    }
}

分布类也不常用稍作了解 

继承

继承的基本原则

namespace Lesson13_继承_继承的基本规则
{
    class Person
    {
        public string? name;
        public int age;

        public Person()
        {
            name = null;
            age = 0;
        }
        public Person(string? name, int age)
        {
            this.name = name;
            this.age = age;
        }

        /// <summary>
        /// 介绍自己
        /// </summary>
        public void SaySelf()
        {
            Console.WriteLine("我叫{0},今年{1}岁", name, age);
        }
        
        public void GrowUp()
        {
            age++;
        }

    }
    class Teather: Person
    {
        // 职工号
        public int number;
        // 保护的,只能在内部或子类中使用
        protected int testProtected;
        // 私有的,只能在内部使用不能在子类或外部中使用
        private int testPrivate;
        

        public void SaySelfNumber()
        {
            testPrivate = 10;
            Console.WriteLine("我的工号是:{0}", number);
        }
    }

    class TeathingTeather : Teather
    {
        // 老师教的科目
        public string? subject;

        /// <summary>
        /// 介绍自己教的课程
        /// </summary>
        public void SaySelfSubject()
        {
            Console.WriteLine("我教{0}", subject);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Lesson13_继承_继承的基本规则");
            TeathingTeather tt = new()
            {
                name = "咸鱼梦想家", 
                subject = "做饭", 
                number = 1386413,
                age = 18,
            };
            tt.SaySelf();
            tt.SaySelfNumber();
            tt.SaySelfSubject(); 
        }
    }
}

继承就是儿子继承父亲,儿子保留父亲的特征

一般我们称“父亲”为 父类、基类

“儿子”为 子类、派生类

当然子类有父类的父类······的特征

其余参考代码...

里氏替换原则

里氏替换原则就是父类转子类并且兼容

父类 test = new 子类();

 但是因此无法从变量中获取子类的方法所以就有了以下关键字

is

is判断一个对象的值是否是指定的对象
返回值bool

as

将一个对象转换为指定类对象 
返回值:指定类型对象
成功返回指定类对象 失败返回null

这个操作称为解引

以下代码供参考...

namespace Lesson14_继承_里氏替换原则
{
    class GameObject
    {
        public int bloodValue;
        public int attackValue;

        public void Move()
        {
            Console.WriteLine("移动...");
        }
    }

    class Player : GameObject
    {
        // 在C#中@写在变量名前可以避免与关键字冲突,@将作为标识符
        public void Attack(ref GameObject @object)
        {
            @object.bloodValue -= attackValue;
            Console.WriteLine("玩家攻击...");
        }
    }

    class Monster : GameObject
    {
        public void Attack(ref GameObject @object)
        {
            @object.bloodValue -= attackValue;
            Console.WriteLine("怪兽攻击...");

        }
    }

    class Boss : GameObject
    {
        public void Attack(ref GameObject @object)
        {
            @object.bloodValue -= attackValue;
            Console.WriteLine("Boss攻击...");

        }
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Lesson14_继承_里氏替换原则");

            // 里氏替换原则 使用父类容器装载子类
            // 变量类型为GameObject
            GameObject player = new Player();
            GameObject monster = new Monster();
            GameObject boss = new Boss();

            // 由于类型是GameObject,所以无法调用Player的Attack方法
            // player.Attack(); 错误代码

            //is和as
            //is判断一个对象是否是指定的对象
            //返回值bool
            //as:将一个对象转换为指定类对象 
            //返回值:指定类型对象
            //成功返回指定类对象 失败返回null

            if (player is Player)
            {
                Console.WriteLine("player是Player类型...");
            }
            Player p = player as Player;
            Console.WriteLine(p is Player);
            p.Attack(ref monster);
        }
    }
}

其余继承和多态待更新中...

点赞          关注          收藏 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值