一、抽象类(abstract)
1.抽象方法只能存在于抽象类中,抽象类中可以包含抽象成员和非抽象成员。
2.任何继承于抽象类的子类都必须使用override关键字实现抽象类的所有抽象方法,类只能单继承。
3.抽象父类中的抽象成员都必须被非抽象子类实现,所以父类抽象成员必须用public修饰符来修饰。
4.抽象类不能实例化。
5.抽象类不能是密封的或者静态的(即不能用sealed或者static来修饰)。
二、密封类(sealed)
1.sealed修饰的类为密封类,类声明时可防止其他类继承此类,在方法中声明则可防止派生类重写此方法。
2.密封类可以被实例,抽象类和接口均不能被实例。
3.密封方法必须是对基类的虚方法的重写。所以在方法声明中,sealed修饰符总是和override修饰符联用。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Test : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
Test2 test2 = new Test2();
test2.A();//打印结果为"111"
test2.B();//打印结果为"444"
}
public virtual void A()
{
Debug.Log("111");
}
public virtual void B()
{
Debug.Log("222");
}
}
sealed class Test2:Test
{
private new void A() //new 关键字可以隐藏从基类继承的成员,从而可以修改访问修饰符(public-->private)
{
Debug.Log("333");
}
sealed override public void B()//当重写"public"继承成员"Test.B()"时,无法更改访问修饰符public.
{
Debug.Log("444");
}
}
三、委托(参考
https://www.cnblogs.com/hushzhang/p/5901052.html
)
1.委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If … Else(Switch)语句,同时使得程序具有更好的可扩展性。
2.可以将多个方法赋给同一个委托,或者叫将多个方法绑定到同一个委托,当调用这个委托的时候,将依次调用其所绑定的方法。
3.使用委托可以将多个方法绑定到同一个委托变量,当调用此变量时(这里用“调用”这个词,是因为此变量代表一个方法),可以依次调用所有绑定的方法。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum Language
{
English,
Chinese
}
public class TestDelegate : MonoBehaviour
{
// Use this for initialization
void Start ()
{
//方式一
GreetPeople("miao", EnglishGreeting);//早上好!miaomiao
GreetPeople("kui", ChineseGreeting);//早上好!kui
//方式二
//GreetingDelegate delegate1;
//GreetingDelegate delegate2;
//delegate1 = EnglishGreeting;
//delegate2 = ChineseGreeting;
//GreetPeople("miao", delegate1);
//GreetPeople("kui", delegate2);
//方式三 第一次用的“=”,是赋值的语法;第二次,用的是“+=”,是绑定的语法。如果第一次就使用“+=”,将出现“使用了未赋值的局部变量”的编译错误。
//通过委托来直接调用EnglishGreeting 和ChineseGreeting
//GreetingDelegate delegate1;
//delegate1 = EnglishGreeting;
//delegate1 += ChineseGreeting;
//delegate1("miaomiao");//Good Morning! miaomiao 早上好!miaomiao
//方式四
GreetingDelegate delegate1 = new GreetingDelegate(EnglishGreeting);
delegate1 += ChineseGreeting;
GreetPeople("kui", delegate1);//Good Morning! kui 早上好!kui
delegate1 -= EnglishGreeting;
GreetPeople("kui", delegate1);//早上好!kui
}
public void GreetProple(string name)
{
EnglishGreeting(name);
}
public void EnglishGreeting(string name)
{
Debug.Log("Good Morning! " + name);
}
public void ChineseGreeting(string name)
{
Debug.Log("早上好!" + name);
}
public void GreetPeople(string name,Language lang)
{
switch (lang)
{
case Language.English:
EnglishGreeting(name);
break;
case Language.Chinese:
ChineseGreeting(name);
break;
}
}
public delegate void GreetingDelegate(string name);
public void GreetPeople(string name,GreetingDelegate MakeGreeting)
{
MakeGreeting(name);
}
}
四、接口(参考:
https://www.runoob.com/csharp/csharp-interface.html
)
1.接口使用
interface
关键字声明,它与类的声明类似,但是接口无法声明为private、protected、protected internal、private protected。接口声明默认是 public 的,C# 接口中的成员默认是 public 的。
附:
解决方案
就是一个容器,在这个容器里,分成好多层,好多格,用来存放不同的项目。
程序集
就是一个项目,多个项目构成一个解决方案。
一个项目就是一个程序集。一个程序集可以体现为一个dll文件,或者exe文件。
i
nternal(内部)
:限定的是只有在同一程序集中可访问,可以跨类。
protected(受保护)
:限定的是只有在继承的子类中可访问,可以跨程序集。
protected internal
:受保护“或”内部修饰符修饰成员,当父类与子类在同一个程序集中,internal成员可见。当父类与子类不在同一个程序集中,子类不能访问父类internal成员,而子类可以访问父类的ptotected internal成员,即,从当前程序集或从包含类派生的类型,可以访问具有访问修饰符protected internal的类型或成员。(参考:
https://www.jb51.net/article/112789.htm
)
2.接口方法不能用public abstract等修饰。接口内不能有字段变量,构造函数。
3.继承接口的类必须实现接口的所有方法。
4.接口成员不能有 new、static、abstract、override、virtual 修饰符。有一点要注意,当一个接口实现一个接口,这2个接口中有相同的方法时,可用 new 关键字隐藏父接口中的方法。
5.接口没有构造函数,所有不能直接使用 new 对接口进行实例化。接口中只能包含方法、属性、事件和索引的组合。接口一旦被实现,实现类必须实现接口中的所有成员。
附:接口实例:(参考:
http://bbs.bccn.net/thread-297685-1-1.html
)
public class MainLogic : MonoBehaviour
{
public delegate void TestDelegate();
public interface ITestInterface
{
event TestDelegate TestEvent;
void FireAway();
}
public class TestClass : ITestInterface
{
public event TestDelegate TestEvent;
public void FireAway()
{
if (TestEvent != null)
{
TestEvent();
}
}
}
static private void F()
{
Debug.Log("This is called when the event fires.");
}
private void Start()
{
ITestInterface i = new TestClass();
i.TestEvent += new TestDelegate(F);
i.FireAway();//最终运行输出:This is called when the event fires.
}
}
方法、属性、索引、事件实例
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public delegate void TestDelete();
interface ISubjectCourseStateSwitch
{
event TestDelete TestEvent;//事件
int this[int index] { get;set; }//索引
int Name { get; set; }//属性
bool OnRegisterCourseStateSwitchHandler(IObserverCourseStateSwitch observerCourseStateSwitch);//方法
}
6.C# 是单继承,接口可以多继承。
7.接口不能包含字段、构造函数、析构函数、静态成员或常量。
五、静态类(Static)
1.在静态类中,所有成员都必须是静态的。
2.静态类不能被实例化,不能包含实例构造函数,不能有任何实例成员。
3.静态类默认继承自System.Object根类,不能为其指定其他父类。
4.静态类不能使用abstract或者sealed修饰符。
5.静态类成员不能有protected或者protected internal访问保护修饰符。
6.静态成员不能标记为 abstract、virtual、override。
(注:命名空间内定义的元素无法显式声明为private、protected、protected internal、private protected)
六、抽象类与接口的相似和不同之处
(一)相似之处:
1.不能实例化。
2.包含未实现的方法声明。
3.派生类必须实现父类未实现的方法,抽象类实现抽象方法,接口则是实现所有成员。
(二)不同之处:
1.类可以实现无限个接口,但仅能从一个抽象(或其他任何类型)类继承,从抽象类派生的类仍可实现接口,从而得出接口是用来解决多重继承的问题的。
2.抽象类中可以存在非抽象的方法,可接口不能,且它里面的方法只是一个没有具体实现的方法。