override new shadowing

1.什么时候使用override?什么时候使用new? 什么叫shadowing?
(重写父类的方法的时候用override以实现多态,如果父类中的方法不是virtual的也不是abstract的才使用new,shadowing不懂)

Overloads, Overrides, Overridable, Shadows

先是基本概念:

overloads(重载):与现有成员相同的名称来声明属性或方法,但参数列表与原始成员不同;

overrides(重写):将重写从基类继承的成员;

Overridable(可覆盖的):指定属性或过程可由派生类中同名的属性或过程进行重写;

shadows:隐藏基类中一个同名元素或一组重载元素。

 Overloads

之前是一直很confuse,在VS里写代码的时候貌似都没用过overloads,后来查了资料才知道Overloads是VB.NET beta 版遗留下来的关键字,现在已经可以不用写了,仍然存在是为了兼容已有的beta版代码。 其基本用法如下:


Public Overloads Sub a()
    Debug.Writeline("a()")
End Sub
Public Overloads Sub a(ByVal para1 As Integer)
    Debug.Writeline("a(ByVal para1 As Integer)")
End Sub
Public Sub Demo()
    a()
    a(1)
End Sub

(此例说明Overloads的作用,就是允许同名函数的存在,前提是有不同的参数。)

 

在VS里,overloads很多时候都可以省略不写,不过在一些涉及继承方面的内容时,还是需要用到overloads的。在子类中我们希望添加一个重载方法,增强子类功能时候,亦即重载基类中地方法时,就需要用到Overloads. 如下例子:


'基类
Public Class Person
  private mName as string
  private mBirthday as Date

  Public Property Name() as String
   Get
       Return mName
   End Get
   Set(Byval value as string)
       mName = value
   End Set
  End Property

 Public Property Birthday() as String
   Get
       Return mBirthday
   End Get
   Set(Byval value as string)
       mBirthday  = value
   End Set
  End Property

End Class

'子类
Public Class Employee
  Inherts Person
 
 Private mHireDate as Date
 Private mSalary as Double
 Private mNames as New Generic.Dictionary(of NameTypes,String)
 Public Property Name(byval 1 as NameTypes) as String
   Get
       Return mNames(type)
   End Get
   Set(Byval value as string)
      if mNames.ContainsKey(type) then
           mNames.Item(type)=value
      Else
          mNames.Add(type,value)
      end if
   End Set
  End Property
End Class
'(如果这里省略了Overload关键字,Name方法的信实现代码就会遮蔽原来的实现代码)

  

Overridable, Overrides and shadow

在.NET中实现多态有两种方式,覆盖(overrides)和投影(shadow),而投影又分为Shados by Name(就是我们一般用的shadows)和Shadows by

signature(参数序列).

 

Public Class TheBase
    Public Overridable Sub a()
        Debug.Writeline("TheBase")
    End Sub
End Class
Public Class TheInherited
    Inherits TheBase
    Public Overrides Sub a()
        Debug.Writeline("TheInherited")
    End Sub
End Class
Public Class TheShadowed
    Inherits TheInherited
    Public Shadows Sub a()
        Debug.Writeline("TheShadowed")
    End Sub
End Class

'情况一:
Dim c As TheBase
c = New TheBase()
c.a()                 ' 输出 TheBase
c = New TheInherited()
c.a()                 ' 输出 TheInherited
c = New TheShadowed()
c.a()                 ' 输出 TheInherited
'情况二:
Dim c As TheInherited
c = New TheBase()
c.a()                 ' 错误!无效的转换。
c = New TheInherited()
c.a()                 ' 输出 TheInherited
c = New TheShadowed()
c.a()                 ' 输出 TheInherited
'情况三:
Dim c As TheShadowed
c = New TheBase()
c.a()                 ' 错误!无效的转换。
c = New TheInherited()
c.a()                 ' 错误!无效的转换。
c = New TheShadowed()
c.a()                 ' 输出 TheShadowed

 

此例说明Overridable、Overrides、Shadows的用法。

请注意TheBase里面的Overridable,如果没有这一句,后面类TheInherited将无法声明同名过程a(),而TheShadows仍然可以。

Overridable 的意思是:可以被重写的。默认情况下,似乎不能重写基类中方法的行为的,基类必须显式地使用Overridable关键字,指出允许重写地方法。

Overrides 的意思是:重写原来的,一般用于子类重写父类的方法。如果没有Overrides关键字,当实现一个与基类中某一方法同名同参数地方法时,会得到一个编译错误。

Shadows 的意思是: 指示该变量隐藏基类中的同名编程元素或重载元素集。任何类型的声明元素均可用其他任何类型来隐藏。隐藏的元素在隐藏它的派生类中不可用。仅可以在模块、命名空间或文件级中使用   Shadows。这意味着可以在源文件中或者在模块、类或结构内(但不在过程内)声明隐藏变量。如果指定了   Shadows,也可以省略Dim关键字。不能在同一变量声明中同时指定   Static   和   Shadows。

 在运行的例子中我们可以清晰地看到,无论变量c的定义是什么,VB.NET都会尽量寻找到最后被定义的那个成员。也就是说,如果被重写了,那么就找“从变量类型开始,到这个变量所指对象实际上的类为止,最后一次被重写(Overrides)的那个成员”。(当然,如果找不到,那么还会往变量类型的祖先那个方向上去找。)

简单点讲就是说,无论c怎么定以,如果他指向的是一个TheBase,他就找“到TheBase为止最后一次被重写的那个Sub a()”。如果他指向的是一个TheInherited,就找“到TheInherited为止最后一次被重写的那个Sub a()”,也就是TheInherited里面的那个。

 对于TheShadowed来说,情况稍微复杂一点:

由于TheShadowed里面所写的那个a()被声明为Shadows的,也就是说这个a()跟TheBase和TheInherited里面的没有关系,于是从变量c的基类(TheBase)开始找,一直找到变量所指对象的类型TheShadowed,发现变量c的类型(无论是TheBase还是TheInherited)里面的那个a()最后一次被重写是在TheInherited里面(注意:TheShadows里面的a()跟它没关系),于是只要c不是Dim .. As TheShadows,那么就会选择调用TheInherited里面的a()了。

 override overload hide obscure shadow概念区别

1。一个实例方法可以覆写(override)在其超类中可访问到的具有相同签名的所有实例方法,VM 将基于实例的
运行期类型来选择要调用的覆写方法

 2。一个域、静态方法或成员类型可以分别隐藏(hide)在其超类中可访问到的具有相同名字(对方法而言就是相同的方法签名)的所有域、静态方法或成员类型。隐藏一个成员将阻止其被继承

3。在某个类中的方法可以重载(overload)另一个方法,只要它们具有相同的名字和不同的签名。由调用所指定的重载方法是在编译期选定的

4。遮掩(obscure)   一个变量可以遮掩具有相同名字的一个类型(比如System的一个String类型和System.out中的System),只要它们都在同一个范围内:如果这个名字被用于变量与类型都被许可的范围,那么它将引用到变量上。相似地,一个变量或一个类型可以遮掩一个包。
例子:
public class Obscure {
static String System; // Obscures type java.lang.System
public static void main(String[ ] args) {
// Next line won't compile: System refers to static field
System.out.println(“hello, obscure world!”);
}
}

5。一个变量、方法或类型可以分别遮蔽(shadow)在一个闭合的文本范围内的具有相同名字的所有变量、方法或类型。如果一个实体被遮蔽了,那么你用它的简单名是无法引用到它的;根据实体的不同,有时你根本就无法引用到它

现在举一个shadow的例子,注意哦,很重要

package com.yinbodotcc;
public class PrivateClass
{
 public  void sleep(String a)
 {
  System.out.println(".."+a);
 }
 
 public static void sleep2(String a)
 {
  System.out.println(".."+a);
 }
 
 public void call()
 {
  new Thread(){
   public void run()
   {
    //从Thread 那里继承到匿名类中的sleep 方法遮蔽(shadow)
    //了我们想要调用的sleep方法,所以直接sleep("hello")找不到匹配的,所以
    //不可以,会编译出错的。
    //这个时候需要用  PrivateClass.this 来修饰一下子
    //想法,如果取一个不同的名字,则就没有这个问题了。
    PrivateClass.this.sleep("3");
    sleep2("4");
   }
  }.start();
 
  new Thread(new Runnable(){
   public void run(){
   //下面可以的原因是由于,Runnable接口里面没有定义sleep函数
   sleep("4");
    }
   }).start();
 }
 
 public static  void main(String[] args)
 {
  PrivateClass p=new PrivateClass();
  p.call();
 }
}

  

2.解释virtual、sealed、override和abstract的区别
(virtual申明虚方法的关键字,说明该方法可以被重写,sealed说明该类不可被继承,override重写基类的方法,abstract申明抽象类和抽象方法的关键字,抽象方法不提供实现,由子类实现,抽象类不可实例化。)

 new

     new 关键字可以显式隐藏从基类继承的成员。隐藏继承的成员意味着该成员的派生版本将替换

基类版本。也就说在使用派生类的方法是调用的方法是New关键字新定义出来的方法,而不是基类的

方法。

   在不使用 new 修饰符的情况下隐藏成员是允许的,但会生成警告。使用 new 显式隐藏成员会取

消此警告,并记录代之以派生版本这一事实。

     Virtual

     Virtual 关键字允许在派生类中重写这些对象,默认情况下,方法是非虚拟的,不可以重写非


虚方法,virtual关键字不可以与static、abstract、private、override一起使用。

    Virtual关键字又是和override紧密不可分的,如果要实现Virtual方法就必须要使用override

或new关键字(new和override产生的机理不同)。

     abstract

         在类声明中使用abstract修饰符以指示某个类只能是其他类的基类。标记为抽象或包含在

抽象类中的成员必须通过从抽象类派生的类来实现。抽象类不能实例化。

        抽象方法声明不提供实际的实现,所以没有方法体;方法声明只是以一个分号结束,并且

在签名后没有大括号 ({ })。

         sealed

         密封方法会重写基类中的方法,但其本身不能在任何派生类中进一步重写。密封类不能被

继承。

        当应用于方法或属性时,sealed修饰符必须始终与override一起使用。

     Override

     Override关键字主要是提供派生类对基类方法的新实现,重写的基类方法必须和Override的方

法具有相同的签名

 

3.Foo.Bar, Version=2.0.205.0, Culture=neutral, PublicKeyToken=593777ae2d274679d 解释这个字符串每个部分的重要性和作用
(程序集的名字、版本、Culture不知道,公钥,这些用于GAC中申明一个唯一的程序集)

 一个程序集通常包括4个自定义属性,用来惟一识别程序集,它们是文件名(无扩展名)、版本号、区域性标识和公钥标记,比如:

  "Hello, version=1.0.0.0, culture=neutral, publicKeyToken=9ebd24cc40ff21fd"

  其中publicKeyToken是公钥的64位散列值,可以唯一标识程序集,拥有公钥标记的程序集称为强名称程序集,强名称程序集可以防篡改;可以安装到GAC中,为多个程序集所共享;还可以实施版本策略(不同版本的强名称程序集被认为是不同的程序集)。而公钥标记为空的程序集只能存在于所引用的程序集的目录以及子目录中,也无法实施版本策略(引用它的程序集会忽略版本号)。

 4.解释public、protected、private和internal的区别 

public可被内外访问

protected只能被内部和之类访问

private只能内部访问

internal只能在该程序集中被访问

 

5.使用Primary Interop Assembly (PIA)有什么好处?
反射,为测试方法加了Attribute

  

6.NUnit是通过什么机制获知需要测试哪些方法的?
(将发生的异常对象抛出,另一个只是抛出异常,并没有抛出原异常对象)

7.catch(Exception e){throw e;}和catch(Exception e){throw;}的区别
 

8.typeof(foo)和myFoo.GetType()的区别?
 

9.public class c{ public c(string a) : this() {;}; public c() {;} } 解释第一个构造函数中发生了什么?这个构造函数有什么用?
(第一个构造函数调用了第二个构造函数,这个构造函数构造了一个c对象的实例。)

  

10.this是干嘛用的?能够用在static方法中


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/liangweiwei130/archive/2009/07/19/4360863.aspx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值