C sharp中面向对象的一些基础概念

1. OOP –Object Oriented Programming

  • 实例化类

    1
    2
    3
    4
    baseclass bc = new  baseclass();
    subclass sc = new subclass();
    bc.Func();
    sc.Func();
  • 里氏转换

    • 子类对象可以直接赋值给父类变量
    • 子类可以调用父类对象,但是父类只有调用自己
    • 父类中如果是子类对象,则可以将父类强制转换为子类
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      //----------------------------------A.里氏转换知识点:----------------------------------
      //里氏转换原则1.子类对象可以直接赋值给父类变量
      sc.Alphabet = total.T;
      bc.Alphabet = sc.Alphabet;
      //里氏转换原则2.子类可以调用父类对象,但是父类只有调用自己
      sc.bsfun();
      //里氏转换原则3.父类中如果是子类对象,则可以将父类强制转换为子类
      baseclass bc2 = new subclass();
      subclass sc2 = new subclass();
      sc2 = (subclass)bc2

2. 抽象类以及抽象类不能被实例化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
//a. 首先定义一个抽象类shape,包含一个抽象方法CalculateArea
public abstract class Shape
{
//抽象方法
public abstract double CalculateArea();
//抽象类中也可以存在普通方法
public void Display()
{
Console.WriteLine("display");
}
}

//b. 创建两派生类Circle和Rectangle,继承自基类
public class Circle:Shape
{
public double Radius{get;set;}

public Circle(double radius)
{
Radius = radius;
}

//重写基类抽象方法
public override double CalcualteArea()
{
return Math.PI*Radius*Radius;
}
}

public class Rectangle:Shape
{
public double Width{get;set;}
public double Height{get;set;}

public Rectangle(double width, double height)
{
Width = width;
Height = height;
}

//重写基类抽象方法
public override double CalculateArea()
{
return Width*Height;
}
}

//c. 使用派生类
class Program
{
static void main(string[] args)
{
//创建圆形对象
Shape circle = new Circle(5);
circle.Display();

//创建矩形对象
Shape rectangle = new Rectangle(6,4);
rectangle.Display();
}
}

3. 静态类

1
2
3
4
5
6
7
8
9
//----------------------------------B.静态字段知识点:----------------------------------
//测试静态字段,
//静态字段可以被重新赋值
//实例或者对象可以在程序中开拓多个空间,即可以存在多个存储区,但是static在程序里面只会被开拓为一个内存区,不能被示例化。
//静态字段,静态方法都用类名.去调用
baseclass bc = new baseclass();
bc.name = "Test";
baseclass.address = "四川";
Console.WriteLine(baseclass.address);

4. 委托

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//_______________________________delegate test____________________________________
//1.委托一个和被委托方法一致的类型
public delegate void setCallBack(int val);

//写出需要被委托的方法
public void setValue(int value)
{
textBox2.Text = value.ToString();
}
//需要新建线程来实现的方法
public void txtBox()
{
setCallBack sV = new setCallBack(setValue);
for (int i = 0; i < 100000; i++)
{
//invoke,在该textBox2控件上执行委托,invoke配合委托使用,要求传入一个委托方法和参数
textBox2.Invoke(sV,i);
//this.Invoke(sV, i);//this表示form,这种用法是可以的
//不使用invoke,报错:'Cross-thread operation not valid: Control 'textBox2' accessed from a thread other than the thread it was created on.'
//setValue(i);//sV(i);
}
}

//专门用于测试跨线程
private void button5_Click(object sender, EventArgs e)
{
Thread th = new Thread(txtBox);
th.IsBackground = true;
th.Start();
}

5. 嵌套类

1
2
3
4
5
//----------------------------------D.嵌套类知识点:----------------------------------
//访问嵌套类
//嵌套类的简单理解就是类里面写类
baseclass.Person bc1 = new baseclass.Person();
bc1.run();

6. 匿名类

1
2
3
4
5
6
7
8
//----------------------------------E.匿名类知识点:----------------------------------
//匿名类定义在方法或者函数里面
//定义一组匿名类
//匿名类一般用于存储一组只读属性
//匿名方法lambda,和py用法差不多
var lam = new { Name = "匿名", Properity = "只读" };
Console.WriteLine("{0}+{1}", lam.Name, lam.Properity);
Console.ReadKey();

7. 密封类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//----------------------------------F.密封类知识点:----------------------------------
//实例化密封类
//sealed
seal se = new seal();
se.run();

//创建一个密封类
//这是一个密封类,不能被子类找到和继承
public sealed class seal
{
public void run()
{
Console.WriteLine("这是一个密封类,不能被子类找到和继承");
Console.ReadKey();
}

}

8. Object类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//----------------------------------G.Object类,拆箱装箱知识点:----------------------------------
//对object,拆箱和装箱进行讲解
public class test
{
//object类
//object里面公开的方法,可以被任何子类找到(Equals/GetHashCode/GetType/ToString)
//按F12查看帮助
//注意看大小写Object的区别,大写是类,小写是类型关键字
object ob;
Object ob1;

//装箱和拆箱
//装箱-值类型>引用类型
//拆箱-引用类型>值类型
//两种类型只有存在继承关系的时候,才可能出现装箱和拆箱操作。
//装箱拆箱本质是堆空间和栈空间的互换,频繁互换会极大的拖累运算速度
public void boxrun()
{
int a = 10;
Console.WriteLine(a);
Console.ReadKey();
object b = a; //装箱
Console.WriteLine(b);
Console.ReadKey();
a = (int)b;//拆箱,需要强转
Console.WriteLine(a);
Console.ReadKey();
}

}


//Attribute--特性,Relfection--反射,可以做到不动程序框架,仅仅是新增类就可以做到把新增的类加到原来的框架里面
//泛型委托:Action和Func
//预处理方法
//泛型数组
//Lambda匿名方法
//以上属于具体需要再百度的高级应用
//process、Thread、Task、async、await等多种方法,用在winform或wpf上。百度具体使用案例即可
//string类和stringbiluder类。用stringbiluder类来解决string不可变性导致的内存占用过多的问题。

9. 父类虚方法以及在子类中重写虚方法

  • 父类建立虚方法
    1
    2
    3
    4
    5
    6
    //----------------------------------父类虚方法 virtual--多态特征----------------------------------
    public virtual void Func()
    {
    Console.WriteLine("父类的虚方法");
    Console.ReadKey();
    }
  • 子类重写虚方法
    1
    2
    3
    4
    5
    6
    7
    //----------------------------------子类重写父类虚方法----------------------------------
    public override void Func()
    {
    // base.Func();---这条表示继承自父类,屏蔽可以只使用子类自己的方法,一般这个base用于公有的初始化方法,不屏蔽可以实现子类继承父类的公有方法。
    Console.WriteLine("子类的虚方法");
    Console.ReadKey();
    }

10. 继承,接口,重载,构造函数,析构函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//----------------------------------子类----------------------------------
//子类继承与父类
//用:表示继承关系
//,后加上接口,接口需要右键选择"快速动作和重构"来生成,不然要报错
//在同一个项目内internal=public修饰符。系统默认用internal修饰类
internal class subclass:baseclass,Interface1
{
//----------------------------------重载,有参构造函数,无参构造函数等同名函数同时存在叫做重载----------------------------------
//1.子类构造函数,无参构造函数
public subclass() { }

//2.有参子类构造函数
public subclass(total m_alp)
{

}
//3.有参继承子类构造函数,用base关键字表示继承自父类
public subclass(total m_alp, int m_wei, float m_siz, string m_sha)
:base(m_alp, m_wei, m_siz, m_sha)
{

}

//----------------------------------析构函数,~函数名();用于手动释放资源----------------------------------

11. 接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
namespace testForObject
{
//----------------------------------接口----------------------------------
//接口,需要单独添加一个接口,接口没有CLASS修饰
//接口用于规范规范扩展的功能
interface Interface1
{
//接口中不能包含字段
//private string name;

//接口中可以包含属性,属性是从哪里来的?
//继承而来,接口可以多继承


//接口中的成员不允许添加访问修饰符,默认都是public,
//接口中的方法不能有方法体
void Fly();

//接口中全是abstract方法。但是却不能使用抽象修饰符。
}
}

12. 接口使用用例

  • 创建一个基类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    class Car
    {
    private string brand;
    public string Brand
    {
    get { return brand; } set { brand = value; }
    }

    public Car(string brand)
    {
    this.brand = brand;
    }

    public void Run()
    {
    Console.WriteLine("{0}品牌的汽车在奔跑", brand);
    Console.ReadKey();
    }
    }
  • 创建一个接口

    1
    2
    3
    4
    5
    //----------------------------------接口测试----------------------------------
    internal interface IFly
    {
    void Fly();
    }
  • 创建两个子类,其中一个会用到接口方法

    1
    2
    3
    4
    5
    6
    7
    class BMWCar:Car
    {
    //初始化
    public BMWCar(string brand)
    :base(brand)
    { }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class BatCar: Car,IFly
    {
    public BatCar(string brand)
    :base(brand)
    { }

    //快速操作和重构,和接口抽象方法保持一直
    public void Fly()
    {
    Console.WriteLine("batCarCanFly");
    Console.ReadKey();
    }
    }

13. 运算符重载

  • 运算符重载的声明方式:operator关键字告诉编译器,它实际上是一个运算符重载,后面是相关运算符的符号;
  • C#要求所有的运算符重载都声明为public和static,这表示它们与它们的类或结构相关联,而不是与实例相关联。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//用来测试C#的运算符重载功能
//运算符重载可以让原来的基本运算具有更多的数据类型
//应用场景:1.如下code可以进行点位的定制化运行,2.可以把基本的数据类型加减法扩展到更多的数据类型,例如时间
internal class Operator_overloading
{
public struct Point
{
public int x; public int y;
public Point(int x, int y)
{
this.x = x; this.y = y;
}
//运算符重载必须要用public static修饰
public static Point operator +(Point a, Point b)
{
return new Point(a.x + b.y, a.y + b.x);
}
public static int operator +(Point a, int b) { return a.x + b; }
}
//测试方法
public static void operatorFun()
{
Point p1 = new Point(1, 2);
Point p2 = new Point(2, 3);
Point p3 = p1 + p2;
Console.WriteLine(p3.x);
Console.WriteLine(p3.y);
Console.WriteLine(p1+2);
Console.ReadKey();
}
}

14. 复合赋值运算符

  • +=:加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数。比如C += A 相当于 C = C + A
  • 在控件相关应用里面,+=用来关联控件事件,比如:
    1
    2
    3
    //事件订阅运算符:+=
    //取消事件订阅运算符:-=
    timer.Tick += timer_Tick;
  • <<=:左移且赋值运算符。比如C <<= 2 等同于 C = C << 2
  • >>=:右移且赋值运算符。比如C >>= 2 等同于 C = C >> 2

C sharp中面向对象的一些基础概念
http://example.com/2024/07/21/C sharp中面向对象的一些基础概念/
作者
xiao cuncun
发布于
2024年7月21日
许可协议