首页 > 代码库 > .NET 基础 一步步 一幕幕[面向对象之new、this关键字]

.NET 基础 一步步 一幕幕[面向对象之new、this关键字]

经常会有人问:小伙子,有没有对象啊,要不要大叔我帮你介绍一个啊,小伙子会说:大叔,不用我自己new一个就好了。(PS:活该你没有对象)

上边当然是一个段子咯,程序员那会没有对象,自己new一个就有了啊。好了进入今天的主题 new和this的关键字。

new关键字

new 关键字可用作运算符、修饰符或约束三种用法:

1) new 运算符:用于创建对象和调用构造函数。

a)   Person person = new Person();//new是一个运算符
(1)在内存中开辟一块合适大小的空间
(2)在这个空间里创建对象
(3)调用这个对象的构造函数
(4)返回这个空间的引用地址

代码展示:

class Program
    {
        static void Main(string[] args)
        {
            Reporter rep = new Reporter("记者", 11, ‘男‘, "偷拍");
            rep.SayHello();
            rep.Test();
            Console.ReadKey();
        }
    }

    public class Person
    {
        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        private int _age;
        public int Age
        {
            get { return _age; }
            set { _age = value; }
        }
        private char _gender;
        public char Gender
        {
            get { return _gender; }
            set { _gender = value; }
        }


        public Person(string name, int age, char gender)
        {
            this.Name = name;
            this.Age = age;
            this.Gender = gender;
        }

        public void Test()
        {
            Console.WriteLine("测试");
        }

        public void SayHello()
        {
            Console.WriteLine("大家好,我是人类");
        }
    }


    public class Reporter : Person
    {
        public Reporter(string name, int age, char gender, string hobby)
            : base(name, age, gender)
        {
            this.Hobby = hobby;
        }


        private string _hobby;

        public string Hobby
        {
            get { return _hobby; }
            set { _hobby = value; }
        }

        public void ReporterSayHello()
        {
            Console.WriteLine("我叫{0},我是一名狗仔,我的爱好是{1},我是{2}生,我今年{3}岁了", this.Name, this.Hobby, this.Gender, this.Age);
        }


        public new void SayHello()
        {
            Console.WriteLine("大家好,我是记者");
        }
    }

  

2) new 修饰符:在用作修饰符时,new 关键字可以显式隐藏从基类继承的成员。

代码展示:

public class BaseClass
    {
        public void functionA()
        {
            Console.WriteLine("BaseFunctionA http://www.cnblogs.com/sosoft/");
        }
        public virtual void functionB()
        {
            Console.WriteLine("BaseFunctionB http://www.cnblogs.com/sosoft/");
        }
    }
   public class DerivedClass:BaseClass
    {
        public new void functionA()
        {
            Console.WriteLine("DerivedFunctionA http://www.cnblogs.com/sosoft/");
        }
        public override void functionB()
        {
            Console.WriteLine("DerivedFunctionB http://www.cnblogs.com/sosoft/");
        }
    }

调用:
BaseClass baseFunction=new DerivedClass();
baseFunction.functionA();
baseFunction.functionB();

运行结果:

 BaseFunctionA http://www.cnblogs.com/sosoft/

 DerivedFunctionB http://www.cnblogs.com/sosoft/

new是隐藏基类方法,override是覆写基类方法。如果要访问new隐藏了的基类成员需要使用base关键字实现。

隐藏和重写基类方法的异同:

1:方法重写:就是在基类中的方法用virtual关键字来标识,然后在继承类中对该类进行重写(override),这样类中的方法已经被重写了,已经失去了功能了。当让基类的对象的引用直接指向继承类的对象时(多态性),调用该方法则是调用的继承类的方法。

2:方法隐藏:无论基类中的方法是否用了virtual关键字,继承类中都可以用new关键字(如果不用new的话,不会产生错误,但会生成一个编译警告)将基类中的方法隐藏,所谓隐藏就是隐藏,不像重写,重写就是原来的(基类中)已经不存在了,而隐藏是原来的还存在。所以当让基类的对象的引用直接指向继承类的对象时(多态性),调用该方法则是调用的基类的方法。

 

3new 约束:用于在泛型声明中约束可能用作类型参数的参数的类型。 

代码展示:

class Person<T> where T : new()
    {
        public T GetName()
        {
            return new T();
        }
    }

    class Boy
    {
        private string _name;

        public string Name
        {
            get{return _name;}
            set { _name = value; }
        }

        public Boy()
        {
            _name = "feng";
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Person<Boy> MBoy = new Person<Boy>();

            Boy a = new Boy();
            Console.WriteLine(a.Name);

            Console.WriteLine(MBoy.GetName().Name);
            Console.ReadKey();
        }
}

运行结果:

打印出2个"feng"

4) new 实现多态

a)  比如通过基类扩展来实现继承式多态.

b)  通过继承接口来实现多态.

代码展示:

class Num
    {
        public static int i = 111;

        public virtual void ShowClassInfo()
        {
            Console.WriteLine("我是基类呵呵");
        }
        public virtual void ShowNum()
        {
            Console.WriteLine("基类的数字是{0}", i.ToString());
        }
    }

    class SubNum : Num
    {
        new public static int i = 222;

        //new 作为修饰符:只是隐藏基类同名方法
        public new virtual void ShowClassInfo()
        {
            Console.WriteLine("我是子类哈哈");
        }

        //override则是覆写了基类的方法
        public override void ShowNum()
        {
            Console.WriteLine("子类的数字是{0}", i.ToString());
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Num num1 = new Num();//new 运算符用法
            num1.ShowNum();
            SubNum sbnum = new SubNum();
            //下面2个调用的都是子类的方法 但是实现机制不一样
            sbnum.ShowNum();//结果:111

            sbnum.ShowClassInfo();//结果:我是子类
            
            //new作为多态的用法:下面是典型的基类继承似多态
            Num num2 = new SubNum();//num2虽然是基类的变量,但是指向了之类SubNum实例的引用

            //调用方法时会在运行期检查虚拟方法表,来确定要调用的方法
            num2.ShowClassInfo();//由于方法只是被隐藏了,没有被重写 所有还是调用的基类的方法

            num2.ShowNum();//方法被覆盖了 所有调用的是子类的方法
            Console.ReadKey();
        }
    }

注意:前方高能:

new关键字在我们的程序中可谓是无时不刻在用到,那么new关键字都可以用在哪些地方呢?考虑以下几个问题:
1、new一个class对象和new一个struct或者new一个enum有什么不同?
  答:new一个class时,new完成2个内容:一是调用newobj命令为实例在托管堆中分配内存,二是调用构造函数实现对象初始化。
  new一个struct时,new运算符用于调用其构造函数,完成实例的初始化。
2、new在.NET中除了创建对象实例外,还可以做什么?   答:new关键字:作为运算符可以创建对象和调用构造函数;   作为修饰符可以用于向基类成员隐藏继承成员,实现派生类中隐藏基类的virtual方法,不能和override共存;   作为约束可以在泛型声明中约束可能用作类型参数的参数类型,即new约束指定泛型类声明中的任何类型参数都必须要有公共的无参构造函数;   使用new关键字实现多态。
3、new运算符可以重载吗?   答:new运算符不可以重载。
4、泛型中new关键字的作用?   答:new运算符用于返回一个引用,指向系统分配的托管堆的内存地址,new分配内存失败,将引发OutOfMemoryException异常。
5、new一个继承下来的方法和override有什么区别?   答:new是隐藏基类方法,override是覆写基类方法。如果要访问new隐藏了的基类成员需要使用base关键字实现。
6、int i和int i = new int()有什么不同?   答:new一个int时,new运算符用于初始化其值为0,使构造函数完成更优越的初始化操作。

 

this关键字

1)、代表当前类的对象

代码展示:

class MyClass
    {
        // 声明一个名为"myVal"的整型字段
       public int myVal = 10;

        // 声明一个构造函数,该函数带一个名为"myVal"的参数
        public MyClass(int myVal)
        {
            // "this"表示MyClass类的当前实例
            // 在这里通过this可以在语义上区分成员名myVal和参数名myVal
            this.myVal += myVal;

            // 使用this作为当前对象的实参传递给Compute方法
            int res = myVal + MyClass1.Compute(this);
        }
    }

  

2)、在类当中显示的调用本类的构造函数  :this

代码展示:

class MyClass
    {
        // 声明一个名为"myVal"的整型字段
       public int myVal = 10;

        // 声明一个构造函数,该函数带一个名为"myVal"的参数
        public MyClass(int myVal)
        {
            // "this"表示MyClass类的当前实例
            // 在这里通过this可以在语义上区分成员名myVal和参数名myVal
            this.myVal += myVal;
        }
    }

  

3)、声明索引器。(PS:这个会在后续的博客中更新)

 代码展示:

 /// <summary>
 /// 
 /// </summary>
 public NameValueCollection Attr = new NameValueCollection();
 
 /// <summary>
 /// /*************************/
 /// /* this用法3:声明索引器 */
 /// /*************************/
 /// </summary>
 /// <param name="key"></param>
 /// <returns></returns>
 public string this[string key]
 {
     set
     {
         Attr[key] = value;
     }
 
     get
     {
         return Attr[key];
     }
 }

4)、扩展对象的方法

代码展示:

/// <summary>
///Person 的摘要说明
/// </summary>
public class Person
{   /// <summary>    
    /// 性别    
    /// </summary>    
    public string Sex { set; get; }
}
 
 
/// <summary>
/// 辅助类
/// </summary>
public static class Helper
{
 
    /// <summary>
    /// /*****************************/
    /// /* this用法4:扩展对象的方法 */
    /// /*****************************/
    /// </summary>
    /// <param name="item"></param>
    /// <returns></returns>
    public static string GetSex(this Person item)
    {
        return item.Sex;
    }
}
调用:

Person person = new Person();
person.GetSex();

  

本篇就到这里了,最后打个小广告:QQ群: .NET 一步步一幕幕  群号:590170361 (加群备注:博客园看到的)

 

.NET 基础 一步步 一幕幕[面向对象之new、this关键字]