this question的答案说“你没有创建接口的实例......”我想知道它是否属实。
任何人都可以告诉我在下面的代码行中创建了哪些实例?为什么?
BaseClass b= new Child();
和
BaseInterface bi= new Child();
编辑:我问的是关于C#.net语言。如果实例是创建了child()。为什么视觉工作室的intellisense会在按下时显示基础成员?
答案 0 :(得分:4)
创建的实际对象是Child类的实例。
“up-cast”只是相同子对象实例的不同视图。
静态类型语言基于表达式的类型限制操作,而不是表达式求值的实际对象的类型。因此,IntelliSense将仅显示适用于b的BaseClass和bi的BaseInterface的方法。
这也是Object o = new Child()
这样的东西有效的原因,即使只能调用Object上定义的方法o,这是一个表达式,类型为Object
实际对象 一个Child的事实可以这样证明:
Child c = new Child();
BaseClass b = c;
BaseInterface bi = c;
c.GetType() == typeof(Child) // => true
object.ReferenceEquals(c, b) // => true
object.ReferenceEquals(c, bi) // => true
答案 1 :(得分:2)
这是一个非常基本的问题,但却非常非常重要。但我不确定这个网站是获得答案的最佳媒介(更重要的是,了解它)。尝试在某处学习OOP课程,或者寻找详细介绍它的在线演示文稿。
简短回答
运行时类型和静态类型是两个非常不同的东西。
更长的答案:
在静态类型语言中,如C#(或java,或F#或其他一些),变量始终具有静态类型。静态类型是编译器证明变量的类型,因为你告诉它它是,或者因为它推断了它(例如在var或lambda参数的情况下)。
一些例子:
int i; //i is of type int
BaseClass b; //b is of class BaseClass
IEnumerable<int> list; //list implements interface IEnumerable<int>
var s = "foo"; //s is inferred to be of type string
这是静态输入。它表示变量属于给定类型。它并不意味着变量中的对象是这种类型(对于接口来说甚至都没有意义!),它只是意味着编译器已经证明内部对象可以赋值给这种类型(这正好意味着它可以是放入该类型的变量/字段中。)
对比运行时类型。运行时类型是实例的实际类型。它只是一个运行时的东西,编译器无法访问它。这是有效的。
静态进行方法和属性调用时,只能从静态类型调用属性和方法。只是因为它是编译器可以知道的唯一类型。当你写作
BaseInterface bi= new Child();
您有效地告诉编译器“我要求您忘记此对象是Child
,将其视为BaseInterface
”。这正是编译器的作用:您无法访问特定于Child
类的bi的成员。
事实上,这种分配只是进行两种截然不同的操作的简短方法。它与
相同BaseInterface bi; // I create a "bi" variable. Its static type is BaseInterface
bi = new Child() // Instanciate an object of runtime type Child and assign it to the bi variable
为变量赋值不会改变其静态类型。
答案 2 :(得分:2)
BaseClass b = new Child(); - new Child()
调用类Child的构造函数初始化对象(创建新实例),引用类型为Base类。
因此,如果BaseClass a具有baseClassMet()并且类Child()具有aditional方法childMet(),则可以调用仅在BaseClass中定义的方法。
和
BaseInterface bi = new Child();首先使用接口,您无法直接实例化接口。您可以为接口分配实现该接口的类。
所以在这种情况下,我们假设Base接口有一个方法定义void interfMet();
如您所知,在实现此接口的类中,您有义务实现此方法。
对象引用bi是BaseInterface的类型,只能访问接口声明的方法。您不能使用Child类的bi(接口引用类型)方法。
如果你真的想要访问Child的方法,你必须进行演员表演。
我希望这会对你有所帮助。
interface BaseInterface{
void interMet();
}
class BaseClass{
void baseClassMet(){
System.out.println("baseClassMet method in superclass");
}
}
public class Child extends BaseClass implements BaseInterface{
//overrided method
void baseClassMet(){
System.out.println("baseClass method in extended class");
}
//method of child
void childMet(){
System.out.println("Child met");
}
public void interMet() {
System.out.println("Implemented method");
}
public static void main(String[] args) {
Child c = new Child();
c.baseClassMet();// prints "baseClass method in extended class"
BaseClass b = new Child();
b.baseClassMet();// prints "baseClass method in extended class"
b.childMet//can't access object method childMet() like this // Does not compile
((Child)b).childMet();//you can do it like this telling the compiler that
//you are sure that b point to a Child object
BaseClass b1 = new BaseClass();
b1.baseClassMet();//prints "baseClassMet method in superclass"
BaseInterface bi = new Child();//assigning bi of type BaseInterface(interface) the object Child
bi.interMet(); // this prints "Child met"
}}
答案 3 :(得分:0)
引用的声明类型是您选择与Child实例交互的透视图,公开说明的透视图是子类的超类或接口。