timothy23242526-类+类的声明,继承和访问控制+重写和多态

023 什么是类 · 语雀

024,025 类的声明,继承和访问控制 · 语雀

026 重写与多态 · 语雀

23-什么是类

24-类的声明和类的访问控制

25-类的继承,类成员访问

26-重写和多态

 

23-什么是类

面向对象OOP-Object Oriented Programming

封装,继承,多态

1.类是一种数据结构-抽象数据结构

类本身是抽象的结果

类是抽象数据和抽象行为的载体

DS-集合数据类型

2.类是一种数据类型

类是1个引用类型,具体到每1个类上,每1个类都是1个自定义类型

类-自定义引用类型

-1.声明变量

-2.创建实例-实例的模板-类的实例化-使用new操作符创建实例

反射-不用new操作符创建实例

3.类代表现实世界的种类

构造器-和类名相同,无返回值

默认构造器

实例构造器-一旦有了实例构造器,编译器就不会再生成默认构造器

实例无参构造器?

实例带参构造器

静态构造器-用来初始化static成员

实例析构器

托管类编程语言-java/c#-Gc垃圾收集器

非托管类编程语言-c/cpp-内存泄漏

反射

dynamic编程

创建对象时

//{}-初始化器-没有显式定义的带参构造器

//()-构造器-显式定义了带参的构造器

namespace cstimothy231
{
    class Program
    {
        static void Main(string[] args)
        {
            //{}初始化器
            Student stu1 = new Student() { ID = 1, Name = "Tom" };
            //()构造器
            Student stu2 = new Student(2, "Tim");
            Console.WriteLine(Student.Amount);//1
        }
    }
    class Student
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public static int Amount;
        public void Report()
        {
            Console.WriteLine($"{this.ID},{this.Name}");
        }
        public Student()
        {
        }
        public Student(int id, string name)
        {
            this.ID = id;
            this.Name = name;
            Amount++;
        }
        static Student()
        {
            Amount = 0;
        }
        ~Student()
        {
            Console.WriteLine("bye");
            Amount--;
        }
    }
}
namespace cstimothy232
{
    class Program
    {
        static void Main(string[] args)
        {
            //反射
            Type t1 = typeof(Student);
            object o1 = Activator.CreateInstance(t1, 1, "Tom");
            Console.WriteLine(o1.GetType().Name);//Student
            //方式1-强转
            Student stu1 = (Student)o1;
            //方式2-as
            Student stu2 = o1 as Student;
            stu1.Report();
            stu2.Report();
            //dynamic编程
            Type t3 = typeof(Student);
            dynamic stu3 = Activator.CreateInstance(t3, 2, "Tim");
            stu3.Report();
        }
    }
    class Student
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public static int Amount;
        public void Report()
        {
            Console.WriteLine($"{this.ID},{this.Name}");
        }
        public Student()
        {
        }
        public Student(int id, string name)
        {
            this.ID = id;
            this.Name = name;
            Amount++;
        }
        static Student()
        {
            Amount = 0;
        }
        ~Student()
        {
            Console.WriteLine("bye");
            Amount--;
        }
    }
}

 

 24-类的声明和类的访问控制

 

声明1个类

创建1个 类的实例/对象 -类的实例化

类声明的位置

1.命名空间里

2.命名空间外-global全局命名空间-workless

3.类体内-成员类

类成员

成员类-嵌套类

cpp类的声明和定义是分开的,也可以在一起

Student.h 

Student.cpp 

Test.cpp

java/c#-声明既定义

错误类型:

编译错误

链接错误-linker链接器

最简单的类声明:

class+identifer类名

{类体}

类名-pascal命名法-单词首字母都大写

特性opt+有效类修饰符组合opt+partail类opt+class+类名+:基类opt

类修饰符

-继承关系

abstarct

sealed

-类的访问控制

1.internal(默认)-internal修饰的类,可以在一个project(assembly)里访问

2.public

-成员类的访问控制

private 

public

pr

otected

internal

-静态类

static

public static class 类名

依赖关系

a依赖b,b就不能再依赖a-不能循环引用!

assembly:2种

.exe

.dll类库

using MyLib.MyNamespace;
namespace cstimothy241
{
    class Program
    {
        static void Main(string[] args)
        {
            Calculator calc = new Calculator();
            Console.WriteLine(calc.Add(2, 3));
        }
    }
}

namespace MyLib.MyNamespace
{
    class Calculator
    {
        public int Add(int a, int b)
        {
            return a + b;
        }
    }
}

using MyLib.MyNamespace;
namespace MyLib.MyNamespace2
{
    class Test
    {
        public Calculator Calculator { get; set; }
    }
}

 

 

 

 

25-类的继承,类成员访问

 

1个类只能有1个基类,但可以有多个基接口

基类-派生类

父类-子类

.net继承体系是单根的

所有继承链的顶端都是Object类

是一个is-a

1个子类的实例也是1个父类的实例,反过来则不成立

用父类类型的变量来引用子类类型的实例

sealed封闭类不能被继承

类修饰符

关于继承的修饰符

abstract-抽象类

sealed-封闭类-不能当做基类被继承

1个类只能有1个基类,但可以有多个基接口

基类-继承,派生

基接口-实现

cpp可以有多个基类,多继承,问题:菱形继承

子类的访问级别不能超越父类的访问级别,可以持平or更低

类的访问级别

internal-默认-限制在程序集

public

ex:

父类是internal,子类是public,编译器报错

父类public,子类internal,OK

继承的本质是子类在父类已有成员的基础上,对父类进行的横向和纵向的扩展。

-子类对父类的成员是全盘继承的-但是父类的实例构造器不能被子类继承

-1个类成员一旦被引入继承链后,就会永远向下传递

cpp/java/c#-静态类型语言-对于类成员只能扩展不能削减

python/javascript-动态类型语言-可以移除类成员

-横向扩展-对类成员个数的扩充

-纵向扩展-对类成员版本的更新(override重写)

c#

托管语言-Gc垃圾收集器

静态语言-继承链上的成员只能扩展不能削减

继承链上的类,创建实例的时候,从基类的构造器开始执行

先调用父类的构造器,再调用子类的构造器

当用子类的类型引用1个子类的实例时,父类的构造器也会被调用

base只能向上访问一层

父类的实例构造器不能被子类继承

类成员的访问级别以类的访问级别为上限

类成员的访问级别:

private-默认-限制在类体内

public

internal-限制在project/assembly

protected-限制在继承链上-跨project/aseembly

internal protected-或的关系-既可以在aseembly访问又可以在继承链上访问

_变量名-private实例字段

面向对象实现风格:

基于类-cpp/java/c#

基于原型-javascript

namespace cstimothy251
{
    class Program
    {
        static void Main(string[] args)
        {
            Car car1 = new Car();
            //两个都是car
            //this和base效果相同
            car1.ShowName();
        }
    }
    class Vehicle
    {
        public string Name { get; set; }
        public Vehicle()
        {
            this.Name = "vehicle";
            Console.WriteLine("vehicle test");
        }
    }
    class Car : Vehicle
    {
        public Car()
        {
            this.Name = "car";
            Console.WriteLine("car test");
        }
        public void ShowName()
        {
            Console.WriteLine(this.Name);
            Console.WriteLine(base.Name);
        }
    }
}


namespace cstimothy252
{
    class Program
    {
        static void Main(string[] args)
        {
            Car car1 = new Car("car");
            car1.ShowName();
        }
    }
    class Vehicle
    {
        public string Name { get; set; }
        public Vehicle(string name)
        {
            this.Name = name;
        }
    }
    class Car : Vehicle
    {
        //public Car():base("n/a")
        //{
        //    this.Name = "car";
        //}
        public Car(string name) : base(name)
        {
            //因为在基类构造器里已经把Name的值设置为name参数的值了
            //所以我们不必要再在Car的构造器里再设置一遍了,让Car的构造器空着就行
        }
        public void ShowName()
        {
            Console.WriteLine(this.Name);
            Console.WriteLine(base.Name);
        }
    }
}

 

java继承:

26-重写和多态

多态基于重写

横向扩展-通过继承增加类成员个数

纵向扩展-通过override重写,对类成员的版本进行迭代

用父类类型的变量引用子类类型的实例-is-a

多态-函数成员的具体行为由实例决定

override重写

父类virtual-cpp中叫虚函数

子类override

不加virtual和override是hide隐藏

hide-workless-work中hide视为一种错误

重写和隐藏发生的条件:

函数成员,可见,签名一致

函数成员-属性/方法

可见-类成员访问级别为public/protected

函数签名一致-方法名和参数列表相同

hide隐藏

用父类类型的变量引用子类类型的实例

调用的是继承链上最新的被override的版本

//重写->多态
//多态-函数成员的具体行为由实例决定
namespace cstimothy262
{
    class Program
    {
        static void Main(string[] args)
        {
            Vehicle vehicle1 = new Vehicle();
            vehicle1.Run();//vehicle run
            Car car1 = new Car();
            car1.Run();//car run

            Vehicle c = new Car();
            c.Run();//car run
        }
    }
    class Vehicle
    {
        public virtual void Run()
        {
            Console.WriteLine("vehicle run");
        }
    }
    class Car : Vehicle
    {
        public override void Run()
        {
            Console.WriteLine("car run");
        }
    }
}


//隐藏hide
namespace cstimothy263
{
    class Program
    {
        static void Main(string[] args)
        {
            Vehicle vehicle1 = new Vehicle();
            vehicle1.Run();//vehicle run
            Car car1 = new Car();
            car1.Run();//car run

            Vehicle v = new Car();
            v.Run();//vehicle run
        }
    }
    class Vehicle
    {
        public void Run()
        {
            Console.WriteLine("vehicle run");
        }
    }
    class Car : Vehicle
    {
        public void Run()
        {
            Console.WriteLine("car run");
        }
    }
}


//hide隐藏
namespace cstimothy264
{
    class Program
    {
        static void Main(string[] args)
        {
            Vehicle v1 = new RaceCar();
            v1.Run(); //car run
            Car c1 = new RaceCar();
            c1.Run();//car run
            RaceCar r1 = new RaceCar();
            r1.Run();//racecar run
        }
    }
    class Vehicle
    {
        public virtual void Run()
        {
            Console.WriteLine("vehicle run");
        }
    }
    class Car : Vehicle
    {
        public override void Run()
        {
            Console.WriteLine("car run");
        }
    }
    class RaceCar : Car
    {
        public void Run()
        {
            Console.WriteLine("racecar run");
        }
    }
}

//属性重写
namespace cstimothy265
{
    class Program
    {
        static void Main(string[] args)
        {
            Vehicle v1 = new Car();
            v1.Run();
            Console.WriteLine(v1.Speed);
        }
    }
    class Vehicle
    {
        private int _speed;

        public virtual int Speed
        {
            get { return _speed; }
            set { _speed = value; }
        }

        public virtual void Run()
        {
            Console.WriteLine("vehicle run");
            _speed = 100;
        }
    }
    class Car : Vehicle
    {
        private int _rpm;
        public override int Speed {
            get { return _rpm / 100; }
            set { _rpm = value * 100; } 
        }

        public override void Run()
        {
            Console.WriteLine("car run");
            _rpm = 5000;
        }
    }
    class RaceCar : Car
    {
        public override void Run()
        {
            Console.WriteLine("racecar run");
        }
    }
}

 

 

C#强类型语言

C#的变量和实例都是有类型的-可以用父类类型的变量引用子类类型的实例-体现多态

python对象有类型,变量无类型,不能用父类类型变量引用子类类型的实例,看不到多态效果-语言层面不支持,但可以通过库来做到

JS和python一样,对象有类型,变量无类型-存在override但看不到多态效果

TypeScript是基于JS的强类型语言,所以TS变量是有类型的,存在多态

C#

强类型语言-变量和实例都是有类型的

托管类型语言-Gc垃圾收集器

静态类型语言-一个成员一旦被添加到继承链上就不能被移除

java是天然重写,不用加virtual和override,也没有hide

java中的@Override只起到辅助检查重写是否有效的功能

 

 python重写-python不是强类型语言-实例有类型,变量无类型-不能用父类类型的变量引用子类类型的实例-看不到多态效果

 

 

 

using System.Collections.Generic;
using System.Linq;// Enumerable
namespace 261
{
    class Program
    {
        static void Main(string[] args)
        {
            var values = Enumerable.Range(0, 10).ToArray();
            var bst = GetTree(values, 0, values.Length - 1);
            DFS(bst);
            Console.WriteLine("————————");
            BFS(bst);
        }
        static Node GetTree(int[] values, int li, int hi)
        {
            if (li > hi)
            {
                return null;
            }
            var mi = li + (hi - li) / 2;
            var node = new Node(values[mi]);
            node.Left = GetTree(values, li, mi - 1);
            node.Right = GetTree(values, mi + 1, hi);
            return node;
        }
        static void DFS(Node node)
        {
            if (node == null)
            {
                return;
            }
            DFS(node.Left);
            Console.WriteLine(node.Value);
            DFS(node.Right);
        }
        static void BFS(Node root)
        {
            var q = new Queue<Node>();
            q.Enqueue(root);
            while (q.Count > 0)
            {
                var node = q.Dequeue();
                Console.WriteLine(node.Value);
                if (node.Left != null)
                {
                    q.Enqueue(node.Left);
                }
                if (node.Right != null)
                {
                    q.Enqueue(node.Right);
                }
            }
        }
    }
    class Node
    {
        public int Value { get; set; }
        public Node Left { get; set; }
        public Node Right { get; set; }
        public Node(int value)
        {
            this.Value = value;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值