今天的程序调试中出现了以下错误,引发了我对base关键字的用法的疑惑,总结一下。
1、base关键字
用法1:
base是为了实现子类的方法中实现父类原有的方法。
this关键字代表本类对象,base关键字代表父类对象。
如:
base.property;//调用父类的属性
base.method();//调用父类的方法
以下实例演示了派生类中调用用基类的方法,注意virtual、override关键词的使用。
(1)virtual关键字用于修改方法、属性、索引器或事件声明,并使它们可以在派生类派生类中被重写。注意静态属性上使用virtual关键字时错误的。
(2)override关键词用于扩展或修改继承的方法、属性、索引器或事件的抽象实现或虚实现。
public class Person //父类
{
protected string ssn = "444-55-6666";
protected string name = "John L. Malgraine";
public virtual void GetInfo()
{
Console.WriteLine("Name: {0}", name);
Console.WriteLine("SSN: {0}", ssn);
}
}
class Employee : Person //派生类
{
public string id = "ABC567EFG";
public override void GetInfo()
{
// Calling the base class GetInfo method:
base.GetInfo();
Console.WriteLine("Employee ID: {0}", id);
}
}
class TestClass
{
static void Main()
{
Employee E = new Employee();
E.GetInfo();
}
}
/*
Output
Name: John L. Malgraine
SSN: 444-55-6666
Employee ID: ABC567EFG
*/
注意:访问父类(基类)成员只能在构造函数、实例方法或实例属性中进行,因此,从静态方法中使用base关键是错误的。我以上错误的原因就是因为静态方法中使用了base。
用法2:base关键字还可以指定创建派生类实例时应调用的基类的构造函数。
public class BaseClass //父类
{
int num;
public BaseClass() //构造函数
{
Console.WriteLine("in BaseClass()");
}
public BaseClass(int i) //构造函数
{
num = i;
Console.WriteLine("in BaseClass(int i)");
}
public int GetNum()
{
return num;
}
}
public class DerivedClass : BaseClass //派生类
{
// This constructor will call BaseClass.BaseClass()
public DerivedClass() : base() //派生类的构造函数调用基类的构造函数
{
}
// This constructor will call BaseClass.BaseClass(int i)
public DerivedClass(int i) : base(i) //派生类的构造函数调用基类的构造函数
{
}
static void Main()
{
DerivedClass md = new DerivedClass();
DerivedClass md1 = new DerivedClass(1);
}
}
/*
Output:
in BaseClass()
in BaseClass(int i)
*/
2、this关键字
用法1:
this代表当前类的实例对象
namespace Demo
{
public class Test
{
private string scope = "全局变量";
public string getResult()
{
string scope = "局部变量";
// this代表Test的实例对象
// 所以this.scope对应的是全局变量
// scope对应的是getResult方法内的局部变量
return this.scope + "-" + scope;
}
}
class Program
{
static void Main(string[] args)
{
try
{
Test test = new Test();
Console.WriteLine(test.getResult());
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
finally
{
Console.ReadLine();
}
}
}
}
用法2:this串联构造函数
namespace Demo
{
public class Test
{
public Test()
{
Console.WriteLine("无参构造函数");
}
// this()对应无参构造方法Test()
// 先执行Test(),后执行Test(string text)
public Test(string text) : this()
{
Console.WriteLine(text);
Console.WriteLine("有参构造函数");
}
}
class Program
{
static void Main(string[] args)
{
try
{
Test test = new Test("张三");
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
finally
{
Console.ReadLine();
}
}
}
}
3、 static关键字
使用 static 修饰符声明属于类型本身而不是属于特定对象的静态成员。static 修饰符可用于类、字段、方法、属性、运算符、事件和构造函数,但不能用于索引器、析构函数或类以外的类型。
静态方法与非静态方法
a、静态方法的调用
类.静态方法名([参数列表])
非静态方法的调用
类 对象 = new 类的构造函数([参数列表])
对象.非静态方法名([参数列表])
静态方法是属于类的,而非静态方法是属于对象的;
b、内存的初始化
静态成员是在第一次使用时进行初始化。非静态的成员是在创建对象的时候。
静态构造函数只能被执行一次;非静态的构造函数可以根据需要进行多次使用。
c、内存中存储
静态的只有一块全局内存空间,非静态的可以有多块内存空间(副本)
d、释放
静态的一旦创建则在全局区一直存放,直到应用程序结束。非静态的则是由new关键字在堆中创建的。可以有多个副本。由GC进行释放。
注意:
(1)static变量及方法不用实例化对象就可以用类名.静态变量和类名.静态方法这种方式进行访问,这使得访问更加方便,不用手工实例化对象。对于某些只读变量和方法来说很适合共享。
(2)static与非static最大的区别就是static类型的变量及方法在调用的时候就在内存中分配了地址,且这个地址只有一份,故static可以直接访问。而非static必需手工去实例化该类,以对象的方式去访问变量和方法。
(3)在一个静态方法里去访问该类的非静态变量或方法,由于static是属于类本身的,是在类被调用的时候,static类型就已经生成,而非static此时并没有生成,它不属于这个类本身,它是属于这个类的对象。故在没有实例化成对象的时候,在静态方法中访问非静态是根本找不到它们的,它不属于这个类。
(4)在非静态方法中去访问静态,由于类被调用时,静态变量和方法就已经生成,也就是说它们属于这个类。既然已经存在,故不管是在静态方法中,还是非静态方法中都可以访问到它们。
(5)this表明对象本身,而在静态方法中并没有对象概念存在,它只有类本身这个概念,它和对象是属于两种互拆的状态,即我中无你,你中无我的情况。也就是说你用对象名.静态变量或对象名.静态方法是不可访问的。
(6)每个类都必须有构造函数,否则此类无法实例化成对象。而我们有时定义的类可以不写它的构造函数,这是因为编译器会帮我们加上一个静态的空构造函数。这样才能实例化。也可以用静态构造函数去初始化静态变量。