C#基础--类/接口/成员修饰符,多态、重载、重写,静态和非静态


类/接口/成员修饰符

C#修饰符---接口:

接口默认访问符是internal
接口的成员默认访问修饰符是public

C#修饰符--类:

public、internal、 partial、abstract、sealed、static

C#修饰符--类成员修饰符:

public、protected、private、internal、sealed、abstract、virtual、override、readonly、const

简单介绍:

Public:最开放,所有的本程序集以及其他的程序集里面的对象都能够访问

Protected:比较开放,自身成员以及子类成员可访问

Private:只有自身成员才能够访问

Internal:本程序集内的成员可以访问

Partial:部分类,可以将一个类分成几部分写在不同文件中,最终编译时将合并成一个文件,且各个部分不能分散在不同程序集中

Abstract:修饰类的时候表示该类为抽象类,不能够创建该类的实例。修饰方法的时候表示该方法需要由子类来实现,如果子类没有实现该方法那么子类同样是抽象类;且含有抽象方法的类一定是抽象类

Sealed:修饰类时表示该类不能够被继承,修饰方法时表示该方法不能被覆写。

Static:修饰类时表示该类时静态类,不能够实例化该类的对象,既然不能实例化该类,那么这个类也就不能够含有对象成员,即该类所有成员为静态;修饰类成员时,该成员为类成员,只能通过【类.成员名】的方式访问

当static修饰构造函数时,构造函数不能含有任何参数,不能含有修饰符,构造函数不能对对象成员进行初始化操作。但是能够对静态成员进行初始化或者调用。不能保证他在什么时候执行,却能保证在第一次使用类型前执行。在静态构造函数中初始化的静态成员为最终初始化结果。

Virtual:修饰方法成员,表示虚方法。父类可以含有该类的实现,子类可以覆写该函数。

Override:表示该方法为覆写了父类的方法。

Readonly:修饰字段,表示该字段为只读字段。

注意:readonly修饰引用类型时由于操作不当可能修改该只读对象状态。例如:

Readonly List< Person> persons=….;

我们可能在某些地方对persons 进行了修改:persons.add(new Person());

Const:修饰字段,表示该字段为只读字段。并且在编译时必须能够明确知道该字段的值,其值是硬编码到程序中去的,修改了该类型成员后需要重新编译才能使修改生效。

而readonly是运行时只读,内容在运行时确定,所以修改了readonly类型成员后无需重新编译即可生效。

Readonly不能修饰局部变量,const可以。

注意:当一个类或方法没有被任何修饰符修饰时,默认为internal:


多态、重载、重写

重写:是指重写基类的方法,在基类中的方法必须有修饰符virtual,而在子类的方法中必须指明override。

格式如下:

1.在基类中:

1 public virtual void myMethod()
2 {
3 }

2.在子类中:

1 public override void myMethod()
2 {
3 }

重写以后,用基类对象和子类对象访问myMethod()方法,结果都是访问在子类中重新定义的方法,基类的方法相当于被覆盖掉了。

重载:用于在给定了参数列表和一组候选函数成员的情况下,选择一个最佳函数成员来实施调用。

1 public void test(intx,inty){}
2
3 public void test(intx,refinty){}
4
5 public void test(intx,inty,stringa){}

重载的特征:

  • 方法名必须相同
  • 参数列表必须不相同,与参数列表的顺序无关
  • 返回值类型可以不相同

但如果有泛型,就要注意了!

多态:c#的多态性主要体现在类的继承上

子类继承父类的时候,可能出现同名但方法定义不同的情况, 所以在子类中会将原方法覆盖,实现自身的要求.

总结一句话:通过继承实现的不同对象调用相同的方法,表现出不同的行为,称之为多态。

需要注意的地方有两点:

  1. 可以在子类中被重写的方法一定要被标记成virtual(虚拟), abstract(抽象), override(重写)标记为virtual 和abstract 的函数就是为了重写而创建的,标记为override的函数本身是由前两种函数重写而来的,所以它可以被重写也是顺理成章的了;
  2. 重写的函数必须在子类中出现,而且任何一个父类的函数在其一个子类中只能被重写一次。(这一点很好理解,当你要重写两次时,该子类中将定义两个返回类型,方法名称 和参数列表都相同的函数,这肯定是不可能的)。

例子1:

代码public class Animal{public virtual void Eat(){Console.WriteLine("Animal eat");}}public class Cat : Animal{public override void Eat(){Console.WriteLine("Cat eat");}}public class Dog : Animal{public override void Eat(){Console.WriteLine("Dog eat");}}class Tester{static void Main(string[] args){Animal[] animals = new Animal[3];animals[0] = new Animal();animals[1] = new Cat();animals[2] = new Dog();for (int i = 0; i < 3; i++){animals[i].Eat();}}}

输出结果:

Animal eat...

Cat eat...

Dog eat...

在上面的例子中,通过继承,使得Animal对象数组中的不同的对象,在调用Eat()方法时,表现出了不同的行为。

多态的实现看起来很简单,要完全理解及灵活的运用c#的多态机制,也不是一件容易的事

例子2:override实现多态

多层继承中又是怎样实现多态的。比如类A是基类,有一个虚拟方法method()(virtual修饰),类B继承自类A,并对method()进行重写(override修饰),现在类C又继承自类B,是不是可以继续对method()进行重写,并实现多态呢?看下面的例子。

 1 代码
 2
 3 public class Animal
 4     {
 5         public virtual void Eat()
 6         {
 7             Console.WriteLine("Animal eat");
 8         }
 9     }
10
11     public class Dog : Animal
12     {
13         public override void Eat()
14         {
15             Console.WriteLine("Dog eat");
16         }
17     }
18
19     public class WolfDog : Dog
20     {
21         public override void Eat()
22         {
23             Console.WriteLine("WolfDog eat");
24         }
25     }
26
27     class Tester
28     {
29         static void Main(string[] args)
30         {
31             Animal[] animals = new Animal[3];
32
33             animals[0] = new Animal();
34             animals[1] = new Dog();
35             animals[2] = new WolfDog();
36
37             for (int i = 0; i < 3; i++)
38             {
39                 animals[i].Eat();
40             }
41         }
42 }

运行结果为:

Animal eat...

Dog eat...

WolfDog eat...

在上面的例子中类Dog继承自类Animal,对方法Eat()进行了重写,类WolfDog又继承自Dog,再一次对Eat()方法进行了重写,并很好地实现了多态。不管继承了多少层,都可以在子类中对父类中已经重写的方法继续进行重写,即如果父类方法用override修饰,如果子类继承了该方法,也可以用override修饰,多层继承中的多态就是这样实现的。要想终止这种重写,只需重写方法时用sealed关键字进行修饰即可。

例子3:abstract-override实现多态

用abstract修饰的抽象方法。抽象方法只是对方法进行了定义,而没有实现,如果一个类包含了抽象方法,那么该类也必须用abstract声明为抽象类,一个抽象类是不能被实例化的。对于类中的抽象方法,可以再其派生类中用override进行重写,如果不重写,其派生类也要被声明为抽象类。看下面的例子。

 1 代码
 2
 3     public abstract class Animal
 4     {
 5       public abstract void Eat();
 6     }
 7
 8     public class Cat : Animal
 9     {
10         public override void Eat()
11         {
12             Console.WriteLine("Cat eat");
13         }
14     }
15
16     public class Dog : Animal
17     {
18         public override void Eat()
19         {
20             Console.WriteLine("Dog eat");
21         }
22     }
23
24     public class WolfDog : Dog
25     {
26         public override void Eat()
27         {
28             Console.WriteLine("Wolfdog eat");
29         }
30     }
31
32     class Tester
33     {
34         static void Main(string[] args)
35         {
36             Animal[] animals = new Animal[3];
37
38             animals[0] = new Cat();
39             animals[1] = new Dog();
40             animals[2] = new WolfDog();
41
42             for (int i = 0; i < animals.Length; i++)
43             {
44                 animals[i].Eat();
45             }
46         }
47     }

运行结果为:

Cat eat...

Dog eat...

Wolfdog eat...

从上面可以看出,通过使用abstract-override可以和virtual-override一样地实现多态,包括多层继承也是一样的。不同之处在于,包含虚拟方法的类可以被实例化,而包含抽象方法的类不能被实例化。


静态和非静态

静态类和非静态类

静态类与非静态类的重要区别在于静态类不能实例化,也就是说,不能使用 new 关键字创建静态类类型的变量。在声明一个类时使用static关键字,具有两个方面的意义:首先,它防止程序员写代码来实例化该静态类;其次,它防止在类的内部声明任何实例字段或方法。

静态类是自C# 2.0才引入的,C# 1.0不支持静态类声明。程序员必须声明一个私有构造器。私有构造器禁止开发者在类的范围之外实例化类的实例。使用私有构造器的效果与使用静态类的效果非常相似。

两者的区别:
私有构造器方式仍然可以从类的内部对类进行实例化,而静态类禁止从任何地方实例化类,其中包括从类自身内部。静态类和使用私有构造器的另一个区别在于,在 使用私有构造器的类中,是允许有实例成员的,而C# 2.0和更高版本的编译器不允许静态类有任何实例成员。使用静态类的优点在于,编译器能够执行检查以确保不致偶然地添加实例成员,编译器将保证不会创建此 类的实例。静态类的另一个特征在于,C#编译器会自动把它标记为sealed。这个关键字将类指定为不可扩展;换言之,不能从它派生出其他类。

静态类的主要特性:
1:仅包含静态成员。
2:无法实例化。
3:是密封的。
4:不能包含实例构造函数。

静态成员

1:非静态类可以包含静态的方法、字段、属性或事件;
2:无论对一个类创建多少个实例,它的静态成员都只有一个副本;
3:静态方法和属性不能访问其包含类型中的非静态字段和事件,并且不能访问任何对象的实例变量;
4:静态方法只能被重载,而不能被重写,因为静态方法不属于类的实例成员;
5:虽然字段不能声明为 static const,但 const 字段的行为在本质上是静态的。这样的字段属于类,不属于类的实例。因此,可以同对待静态字段一样使用 ClassName.MemberName 表示法来访问 const 字段;

6:C# 不支持静态局部变量(在方法内部定义静态变量)。

静态构造函数

1:静态类可以有静态构造函数,静态构造函数不可继承;
2:静态构造函数可以用于静态类,也可用于非静态类;
3:静态构造函数无访问修饰符、无参数,只有一个 static 标志;
4:静态构造函数不可被直接调用,当创建类实例或引用任何静态成员之前,静态构造函数被自动执行,并且只执行一次。

注意:
1:静态类在内存中是一直有位置的;
2:非静态类在实例化后是在内存中是独立的,它的变量不会重复,在使用后会及时销毁,所以不会出现未知的错误。在C#中静态成员是比较敏感的东西,在不是十分确认的情况下不要使用;
3:建议更多地使用一般类(非静态类)。

使用选择:
当定义的类不需要进行实例化时,我们使用静态类;如果需要实例化对象,需要继承等特性时,应该使用非静态类,并且将统一使用的变量和方法设为静态的,那么所有实例对象都能访问。

转载于:https://www.cnblogs.com/JiYF/p/6122475.html

C#基础--类/接口/成员修饰符,多态、重载、重写,静态和非静态相关推荐

  1. 14.11类的成员修饰符

    成员修饰符 类的所有成员分为:字段,方法 公有成员,在任何地方都能访问 私有成员,只有在类的内部才能访问 私有成员和公有成员的定义不同:私有成员命名时,前两个字符是下划线.(特殊成员除外,例如:ini ...

  2. day03--java基础编程:面向对象,构造方法,代码块讲解,this super,static,final,访问修饰符,方法重写,向上/下造型,main方法,抽象类,接口,设计模式,异常,内部类

    1 Day06–面向对象1 1.1 面向对象 1.1.1 概念 推荐看的书:Thinking in java 概念:所谓的面向对象是一种编程思想,通过这种思想可以把生活中的复杂事情变得简单化,从原来的 ...

  3. day03--java基础编程:面向对象,构造方法,代码块讲解,this super,static,final,访问修饰符,方法重写,向上_下造型,main方法,抽象类,接口,设计模式,异常,内部类

    1 Day06–面向对象1 1.1 面向对象 1.1.1 概念 推荐看的书:Thinking in java 概念:所谓的面向对象是一种编程思想,通过这种思想可以把生活中的复杂事情变得简单化,从原来的 ...

  4. C#的类修饰符和成员修饰符

    一.类修饰符 类修饰符:public.internal. partial.abstract.sealed.static.new.protected.private.protected internal ...

  5. 第四回 基类中的修饰符,应该根据你对架构的理解去定义它们,没有绝对的

    基类中的修饰符,其实就是C#里的那几种修饰符,public ,proteced,internal,privat这四种基础类型,当然也还一个组合类型internal protected,它们都是C#里最 ...

  6. Java接口的修饰符

    Java接口的修饰符可以为(D) A.private B. protected C.final D.abstract 接口: (1)接口用于描述系统对外提供的所有服务,因此接口中的成员常量和方法都必须 ...

  7. Python学习 :面向对象 -- 成员修饰符

    成员修饰符 两种成员 - 公有成员 - 私有成员, __字段名 - 无法直接访问,只能通过内部方法来间接访问私有成员 简例:公有成员与私有成员  class Info:country = '中国' # ...

  8. C#中什么是类,类和对象的关系,类的访问修饰符?

    类以及类和对象的关系以及类的访问修饰符 一.类的概念: 二.类和对象的关系: 三.类的组成: 四.类的创建: 五.类的访问修饰符: 一.类的概念: 类是对于某一类对象的一个统称,类是对象的抽象化,对象 ...

  9. java有关类的三大修饰符

    Abstract 含义: 抽象的 修饰的内容 :        类: 使用abstract修饰的类称为抽象类 抽象类: 特点:不能直接创建对象 语法: 访问权限修饰符 abstract class 类 ...

最新文章

  1. 把委托说透(4):委托与设计模式
  2. GitHub一日千星:开头一张图,自动变成《我的世界》、乐高、十字绣风格,有Python就能跑...
  3. pix2pix, CycleGAN和pix2pixHD(没有公式,容易理解)
  4. SQL语句inner join,left join ,right join连接的不同之处
  5. 【Elasticsearch】es 提高 搜索速度
  6. setint 的用法
  7. 使用 ld 命令链接目标文件生成可执行文件
  8. h5应用 vue 钉钉_快速上手——钉钉H5微应用开发接入
  9. 计算机每次启动时系统时间不更新,电脑每次开机都要重新设置时间
  10. 人工智能如何自我进化
  11. 天童美语育儿书籍推荐《愿你慢慢长大》
  12. Window纯净系统安装详细教程
  13. 用mission planner或者3drradioconfig软件配置X-ROCK数传电台
  14. 【挨踢人物传】小侠唐在飞:“剑胆琴心,成就网络大侠”(第四期)
  15. 操作系统Windows【实验】文件复制
  16. 选择语句switch和循环语句while
  17. // 程序员面试宝典第三版34页,面试题2 ,结果很诡异,指针类型的转换本来意味着指向数据类型的转换,但是似乎不尽然是。
  18. 好听的歌曲,更新记录听过的音乐。。
  19. cf修改游戏客户端是什么意思_网络游戏所谓的修改客户端是怎么回事?
  20. GPIO口的八种工作状态

热门文章

  1. 用hutool进行RSA编码及解码
  2. 从前序与中序遍历序列构造二叉树—leetcode105
  3. No space left on device 解决 Cydia 安装应用错误
  4. CentOS挂载NTFS移动硬盘
  5. C++、python、CUDA性能分析--矩阵乘法
  6. LeetCode每日一题 416. 分割等和子集
  7. 4.如果容器中包含了通过new操作创建的指针,切记在容器对象析构前将指针delete掉
  8. linux mysql操作知识--收藏
  9. DVWA-暴力破解-对‘g0tmi1k’文章的学习笔记
  10. 如何QLayout内部的成员部件之间从左到右依次排列