.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的话,不会产生错误,但会生成一个编译警告)将基类中的方法隐藏,所谓隐藏就是隐藏,不像重写,重写就是原来的(基类中)已经不存在了,而隐藏是原来的还存在。所以当让基类的对象的引用直接指向继承类的对象时(多态性),调用该方法则是调用的基类的方法。
3)new 约束:用于在泛型声明中约束可能用作类型参数的参数的类型。
代码展示:
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();//结果:222 sbnum.ShowClassInfo();//结果:我是子类哈哈 //new作为多态的用法:下面是典型的基类继承似多态
Num num2 = new SubNum();//num2虽然是基类的变量,但是指向了之类SubNum实例的引用 //调用方法时会在运行期检查虚拟方法表,来确定要调用的方法
num2.ShowClassInfo();//由于方法只是被隐藏了,没有被重写 所有还是调用的基类的方法 //结果:我是子类呵呵 num2.ShowNum();//方法被覆盖了 所有调用的是子类的方法 //结果: 222
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关键字]的更多相关文章
- .NET 基础一步步一幕幕[面向对象前言]
面向对象前言 2017年的第一篇博文,好久不写博文了,赶紧补上,感觉在以前的<.NET 基础一步步一幕幕>系列博客中,简短的小知识点已经介绍的差不多的(PS:如果还有别的基础知识点我没有介 ...
- .NET 基础 一步步 一幕幕[面向对象之对象和类]
对象和类 本篇正式进入面向对象的知识点简述: 何为对象,佛曰:一花一世界,一木一浮生,一草一天堂,一叶一如来,一砂一极乐,一方一净土,一笑一尘缘,一念一清静.可见"万物皆对象". ...
- .NET 基础 一步步 一幕幕[面向对象之方法、方法的重载、方法的重写、方法的递归]
方法.方法的重载.方法的重写.方法的递归 方法: 将一堆代码进行重用的一种机制. 语法: [访问修饰符] 返回类型 <方法名>(参数列表){ 方法主体: } 返回值类型:如果不需要写返回值 ...
- .NET 基础 一步步 一幕幕[面向对象之构造函数、析构函数]
构造函数.析构函数 构造函数: 语法: //无参的构造函数 [访问修饰符] 函数名() :函数名必须与类名相同. //有参的构造函数 [访问修饰符] 函数名(参数列表):函数名必须与类名相同. 作用: ...
- .NET 基础 一步步 一幕幕[面向对象之静态、非静态]
静态.非静态 先来看一段代码来区分静态与非静态: using System; using System.Collections.Generic; using System.Linq; using Sy ...
- .NET 基础 一步步 一幕幕[面向对象之堆、栈、引用类型、值类型]
堆.栈.引用类型.值类型 内存分为堆和栈(PS:还有一种是静态存储区域 [内存分为这三种]),值类型的数据存储在栈中,引用类型的数据存储在堆中. 堆.栈: 堆和栈的区别: 栈是编译期间就分配好的内存空 ...
- .NET 基础 一步步 一幕幕 [前言]
.NET 基础 一步步 一幕幕 [前言部分] 本人小白一枚,虽然说从去年就开通博客了,到现在也没有写多少东东,虽然工作了,也没有更好得总结.故此重新祭出博客园法宝,修炼技术,争取早日走上大神之位. 故 ...
- .NET基础 一步步 一幕幕[循环、逻辑语句块]
循环.逻辑语句块 好久不写博客了,断更了好几天了,从上周五到今天,从北京到上海,跨越了1213.0公里,从一个熟悉的城市到陌生的城市,还好本人适应力比较好,还有感谢小伙伴的接风咯,一切都不是事,好 ...
- .NET 基础 一步步 一幕幕 [.NET 简介]
.NET 简介 .NET是 Microsoft XML Web services 平台.是微软用来实现XML,Web Services,SOA(面向服务的体系结构service-oriented ar ...
随机推荐
- What's the use of @ before the path defination
When you define your path const : const string Child_Medical_Pdf = @"~/Media/ChildPdf"; Th ...
- SGU 181.X-Sequence
时间限制:0.5s 空间限制:4M 题意: 令X0=A, Xi=(a*Xi-1^2,b*Xi-1+c)%m; 求Xk,(0<=k<=109),(0<=a,b<=100),(1& ...
- photoshop cc 版本安装失败解决办法
好久没有碰ps,看了下在ps版本都到cc了.忍不住也想尝试最新版本,但是安装出现了很多问题,导致我花了很多时间才搞定,现在分享给大家几点经验吧. Exit Code: Please see speci ...
- SQL 结构化查询语言
SQL 结构化查询语言 一.数据库的必要性: >>作用:存储数据.检索数据.生成新的数据 1)可以有效结构化存储大量的数据信息,方便用户进行有效的检索和访问. 2)可以有效地保持数据信息的 ...
- Wdcp缺少mod_rewite模块
1.下载apache源码包,解压并查找到mod_rewrite.c文件 tar -zxvf httpd-2.2.27.tar.gz cd httpd-2.2.27 [root@localhost ht ...
- phpcms get标签说明
{pc:get sql="SELECT * FROM phpcms_member" cache="3600" page="$page" db ...
- html5系列.基础知识
兼容性问题 创建一个html5页面 <!DOCTYPE html> <html> <head> <meta charset="UTF-8" ...
- YII 小部件 解决多选按钮和单选按钮不在同一水平上 'separator'=>' '
主要是添加separator属性(这里)$hoddy,$sex在控制器里面定义的数组,然后render传过来的 <td> <?php echo $form-> ...
- 设计模式——如何避免在OO设计中违反依赖倒置原则
1 变量不可以包含具体类的引用.一旦new,就对具体类产生依赖,用工厂模式来避开. 2 类不要派生至具体类.用派生抽象类避开. 3 不要覆盖基类已经实现的方法.基类中已实现的方法应该由所有子类共享.
- Node.js REPL终端
REPL表示读取评估和演示打印循环(Read Eval Print Loop),它代表一个命令输入和系统在交互模式的输出响应窗口控制台或Unix/ Linux的shell计算机环境. Node.js附 ...