.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 ...
随机推荐
- Swift中共有74个内建函数
Swift中共有74个内建函数,但是在Swift官方文档(“The Swift Programming Language”)中只记录了7中.剩下的67个都没有记录. 本文将列举Swift所有的内建 ...
- splice 操作符
几乎所有的数组操作都可用 splice 实现. 除了第一个参数,数组,为必须,其余的参数都不是必须的. splice ARRAY, OFFSET, LENGTH, LIST OFFSET 和 LENG ...
- yzoi2226最小步数的详细解法
Description - 问题描述 在各种棋中,棋子的走法总是一定的,如中国象棋中马走“日”.有一位小学生就想如果马能有两种走法将增加其趣味性,因此,他规定马既能按“日”走,也能如象一样走“田”字. ...
- js数学方法应用
找出数组中最大的数 var values = [1, 2, 3, 4, 5, 6, 7, 8]; alert(Math.min.apply(Math,values))//8 这个技巧的关键是把 Mat ...
- jQuery选择器种类整理
选择器概念 jQuery选择器是通过标签.属性或者内容对HTML内容进行选择,选择器运行对HTML元素组或者单个元素进行操作. jQuery选择器使用$符号,等同于jquery,例如: $(“li”) ...
- 在Lufylegend中如何设置bitmap或者sprite的缩放和旋转中心
最近两天有个lufylegend游戏引擎群的群友需要做一个项目,其中要解决的需求是:获取照相机拍摄的图片,根据图片的EXIF信息让图片显示为“正常”情况,并且需要给图片添加一些事件侦听.何为正常呢?就 ...
- unix 环境高级编程-读书笔记与习题解答-第二篇
第四节 输入与输出 上次的笔记中写到的 open, read, write, lseek 以及close ,都是不带缓存的IO函数,这些函数都使用文件描述符进行工作. 上一篇笔记用到的 read(ST ...
- NandFlash
一.概述 1.NandFlash NAND结构能提供极高的单元密度,可以达到高存储密度,比如能达到256M,并且写入和擦除的速度也很快.应用NAND的困难在于flash的管理需要特殊的系统接口. 2. ...
- 项目任务管理(TaskMgr)技术篇
判定是否为枚举型:type.IsEnum 应用原型:如果是枚举返回字符型,如果是其他类型直接返回: object value = pro1.FieldType.IsEnum ? pro1.GetVal ...
- JSP - request - 1
<%@ page language="java" contentType="text/html;charset=utf8" %> <%@ pa ...