一个类实现了多个接口中的方法,在实际应用中是用类来调用方法?,还是用接口来调用方法?
代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;namespace 有关类的技术实验3
{
public interface IMyInterface {
void Method();
}
public interface IMyInterface2
{
void Method2();
}
public class MyClass : IMyInterface, IMyInterface2
{
public void Method()
{
Console.WriteLine("Greetings from IMyInterface ");
} public void Method2()
{
Console.WriteLine("Greetings from IMyInterface2");
}
} class Program
{ static void Main(string[] args)
{
IMyInterface a = new MyClass();
a.Method();
IMyInterface2 b = new MyClass();
b.Method2();
MyClass c = new MyClass();
c.Method();
c.Method2();
Console.ReadKey();
}
}
}实际应用中,是红色的使用的多,还是天蓝色的使用的多?,使用这两种方法技术上的称呼叫什么?
还有
IMyInterface a = new MyClass();
a.Method();
这段代码,听大牛们说,new是创建了一个引用,把地址传给了a,我的问题是,类的地址传给了接口,这样的隐式转换没问题吗?我只看到过,继承类可以隐式地转换给基类... ...
代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;namespace 有关类的技术实验3
{
public interface IMyInterface {
void Method();
}
public interface IMyInterface2
{
void Method2();
}
public class MyClass : IMyInterface, IMyInterface2
{
public void Method()
{
Console.WriteLine("Greetings from IMyInterface ");
} public void Method2()
{
Console.WriteLine("Greetings from IMyInterface2");
}
} class Program
{ static void Main(string[] args)
{
IMyInterface a = new MyClass();
a.Method();
IMyInterface2 b = new MyClass();
b.Method2();
MyClass c = new MyClass();
c.Method();
c.Method2();
Console.ReadKey();
}
}
}实际应用中,是红色的使用的多,还是天蓝色的使用的多?,使用这两种方法技术上的称呼叫什么?
还有
IMyInterface a = new MyClass();
a.Method();
这段代码,听大牛们说,new是创建了一个引用,把地址传给了a,我的问题是,类的地址传给了接口,这样的隐式转换没问题吗?我只看到过,继承类可以隐式地转换给基类... ...
还有
IMyInterface a = new MyClass();
a.Method();
这段代码,听大牛们说,new是创建了一个引用,把地址传给了a,我的问题是,类的地址传给了接口,这样的隐式转换没问题吗?我只看到过,继承类可以隐式地转换给基类... ...
============================================================
红色的使用多还是蓝色的使用的,这里要根据具体情况,看你实例化类偏重于哪种情况。技术上的称呼不好回答。
如果非要说:第一种是:实例化实现了这个接口的类。 第二中是实例化一个类,这个类实现了两个接口。IMyInterface a = new MyClass();
接口是不能实例化的,只能实例化实现了这个接口的类。隐式转换是没有问题的。
只是接口更强调的是对外部提供了那些操作,继承它的类一定要实现它的方法,所以你知道如果一个类继承了一个接口的话,那么
这个类一定提供了接口中声明的方法的实现。你可以将接口看成是提供了一种标准,比如客户提出一个标准,只要我给出满足这个标准的插件,就一定能在客户的程序中正常使用。
基本上,那个大牛们是看c入门书走火入门了,所以生搬硬套地说.net的对象是地址。在.net中,对象就是对象,你不要玩什么“地址”概念,也就不会有此多此一举的困惑。对象有HashCode,但是归根结底还是对象的类型转换,而不是什么地址在两个对象之间的赋值。
MyClass x = new MyClass();
MyClass y=x;
IMyInterface a=(IMInterface)x;
IMyInterface2 b=(IMInterface2)x;
Object c=x;这里,x、y、a、b、c,都是同一个对象,而不是什么地址相同的不同对象。调用a定义的某个方法,其实就是调用x所代表的对象的那个方法,也同时就是调用b多代表的那个对象的那个方法。你甚至可以写: IMyInterface2 d=(IMInterface2)a;对毫不相干的类型的对象进行强制类型转换。
y.GetHashCode();
a.GetHashCode();
b.GetHashCode();
c.GetHashCode();
d.GetHashCode();你会发现是完全一样的。有人说,如果类型B继承自A,那么B的实例中就有一个私有对象指向内部的一个A类型的对象,这是错误的结论,则往往给你带到错误的概念上去推理。在多年以前某些c++的书籍作者是这样写的,甚至某些c++实现也真的是那样实现的,但是这是一个对继承的误解。至少在.net中,并不是这样的。
不能赞同这样的观点,要了解基本原理就要了解本质,归根结底程序还是对内存块的操作,了解c的对象和指针无疑对.net中的
对象的理解有很大帮助。 MyClass x = new MyClass();
MyClass y=x;
IMyInterface a=(IMInterface)x;
IMyInterface2 b=(IMInterface2)x;
Object c=x;这里的x,y,a,b,c其实并不是对象,而是类型分别为MyClass,IMyInterface,Object的引用变量,这些变量的值其实是整型,对应内存中的一个地址,而这个地址就是存储对象的内存块的起始地址。
而真正的对象是通过new操作符在内存中创建的那段内存中的数据结构。做个很简单的实验:using System;public class Program
{
static void Main()
{
A obj1 = new A();
A obj2 = new A();
obj1.i = 10;
Method1(obj1);
Console.WriteLine(obj1.i.ToString());
obj2.i = 10;
Method2(ref obj2);
Console.WriteLine(obj2.i.ToString());
}
static void Method1(A obj)
{
Console.WriteLine((++obj.i).ToString());
}
static void Method2(ref A obj)
{
Console.WriteLine((++obj.i).ToString()) ;
}
}public class A
{
public int i;
}输出:----------------
11
11
11
11
using System;public class Program
{
static void Main()
{
A obj1 = new A();
A obj2 = new A();
obj1.i = 10;
Method1(obj1);
Console.WriteLine(obj1.i.ToString());
obj2.i = 10;
Method2(ref obj2);
Console.WriteLine(obj2.i.ToString());
}
static void Method1(A obj)
{
obj = new A();
obj.i = 15;
Console.WriteLine(obj.i.ToString());
}
static void Method2(ref A obj)
{
obj = new A();
obj.i = 15;
Console.WriteLine(obj.i.ToString()) ;
}
}public class A
{
public int i;
}输出:
15
10
15
15可以看出,例1中的两个方法都改变了实参,而例2中obj1却没有被改变。为什么
如果不知道传参的实质的话这里是很难解释的。引用变量作为参数时传递的是对象的引用,其实它任然是值传递,只不过这里的值,是对象的引用,即地址,型参中引用变量
obj拷贝了它的实参obj1的值,即obj1指向的对象地址,所以,直接通过型参obj去改变对象的状态也会影响到Main中的obj1,
此时相当于
形参-------->堆中的数据结构<------------实参
而如果加上ref强制进行引用传递,此时实际上是将值类型A的引用变量的引用传给了形参,此时的形参相当于引用的引用,即指针的指针,所以此时声明一个新对象并将其引用赋给形参会影响到实参,而同样的操作用值传递就不会影响到实参
此时相当于
形参------->实参--------->堆中的数据结构
CLR也只不过是运行在宿主进程上的一个软件层罢了,归根结底程序运行的机制是相同的,只不过C#是类型安全的而且不允许
使用指针罢了,但是通过标记标记unsafe仍然可以使用指针C++是源头啊,源头啊,源头啊,源头啊(回想1万遍啊1万遍)
就如同汇编是老祖宗啊老祖宗
就如同其实都是机器码啊机器码以上,就是不喜欢看见有人说C++是什么走火入魔阿门
知道为什么这6个操作返回相同的值么,因为这6个引用变量指向的都是同一个对象
还有什么相同的地址不同的对象,大哥。既然是相同的地址,那就是同一个对象。我也不知道说你什么好了
见图
x------>堆中的对象
y---|
a---|
b---|
c---|
d---|
“.”操作是作用在对象上的
可以写程序证明这6个引用变量本身的地址是不同的
关于对象、地址和引用变量,再次表明立场:sp1234关于对象、地址和引用变量的理解有误,Crazy_Xia正解!
sp1234如有不服,我可以开贴来集中讨论这个问题,看看广大程序员的意见。
关于接口的使用,再次强调,像如下代码: IMyInterface a = new MyClass();
a.Method();不推荐在实际中使用。当然,你的例子过于简单,不能看出问题所在。试考虑一个用户类B,在B中使用到某外部对象的方法,此时,若把对象的创建放在B中,像:IMyInterface a = new MyClass(); 这样,则B就依赖于MyClass了,即,B类在编写代码时就必须已知MyClass的存在,将来MyClass的变化会引起B类某些问题,这还是小事。如果IMyInterface的实现类要替换为MyClass2,则就要到B类中修改代码,修改为IMyInterface a = new MyClass2();这就违反了OO的开闭原则,是个大事了。
请查阅设计模式的工厂模式和依赖注入模式,会对你理解这些有所帮助,找到使用接口及其实现类的正确方法。
http://msdn.microsoft.com/zh-cn/library/ms173110.aspx
http://msdn.microsoft.com/zh-cn/library/x9afc042.aspx自己看看,应该就明白了
ref 关键字使参数按引用传递。其效果是,当控制权传递回调用方法时,在方法中对参数的任何更改都将反映在该变量中。若要使用 ref 参数,则方法定义和调用方法都必须显式使用 ref 关键字。
按引用传递值类型是有用的,但是 ref 对于传递引用类型也是很有用的。这允许被调用的方法修改该引用所引用的对象,因为引用本身是按引用来传递的。
{
public void Method()
{
Console.WriteLine("Greetings from IMyInterface ");
} public void Method2()
{
Console.WriteLine("Greetings from IMyInterface2");
}
} 在内存中方法表的分配如下
myclass 入口
IMyInterface 接口入口1 void Method() //相对IMyInterface的偏移量-----》该偏移量地址保存,Method的入口地址
IMyInterface2 接口入口2
void Method2() //相对IMyInterface2---->该偏移量地址保存,Method2的入口地址IMyInterface a = new MyClass();
//将new出来的对象入口地址给了a(呵呵,这里有隐含的转换,实际上是把new出来的对象IMyInterface地址给了a)
a.Method();//根据IMyInterface方法表读取 相对IMyInterface入口偏移量的处保存的,Method2的入口地址,然后执行Method2的入口地址的代码。
建议 lz去博客园找一下《你必须知道的.net》有关对象和对象内存分布相关章节,那里面有详细的分析,我上面只是借c++的观点简单分析,《你必须知道的.net》上的解释倒是更偏向net本身
其实我想说的就是,x、y、a、b、c并不是对象,而是对象的引用,只是引用了同一个对象
有时候这种错误的说法还是很误导新人的
----------------引用MSDN:http://msdn.microsoft.com/zh-cn/library/x9afc042.aspxCustomer object1 = new Customer();
创建类的实例后,将向程序员传递回对该对象的引用。在前面的示例中,object1 是对基于 Customer 的对象的引用。此引用引用新对象,但不包含对象数据本身。实际上,可以在根本不创建对象的情况下创建对象引用:
Customer object2;
建议不要创建像这样的不引用对象的对象引用,因为在运行时通过这样的引用来访问对象的尝试将会失败。但是,可以创建这样的引用来引用对象,方法是创建新对象,或者将它分配给现有的对象
-------------------------
MSDN上面 C#编程指南 章节中有多处使用地址及引用,有何不妥吗?MyClass a = new MyClass();
MyClass b=a;a,b两个变量本身毕竟是存储在栈上的引用变量,a与b毕竟是不同的,当然他们目前都指向堆上同一个MyClass实例。我认为,仍然有必要区分清楚 类的实例(即对象,堆上new出来的那个MyClss实例)和 对对象的引用本身(即引用变量,a和b,他们在栈上的不同位置)。当执行类型转换是,实例是不变的,变化的只是引用该实例的方式而已。如 Object c = (Object)a; 是用一个object类型的引用变量来指向a所指向的那同一个实例。但是变量a被定义为对MyClass的引用,始终只能指向一个MyClass类型(及其子类型)的实例,并且基于a访问该实例时,只能看到MyClass类中的相关成员。
欢迎大家批评,如有人想继续讨论此话题,我来开个贴,向大家再学习学习。就不影响楼主此贴的主旨了。
MyClass x = new MyClass();
MyClass y=x;
IMyInterface a=(IMInterface)x;
IMyInterface2 b=(IMInterface2)x;
Object c=x; x.GetHashCode();
y.GetHashCode();
a.GetHashCode();
b.GetHashCode();
c.GetHashCode();
d.GetHashCode(); 一样是因为他实际是套滴是Type object 类型的方法表,而对于同一对象来说,Type object方法表里那个偏移量处指向的是同一个地址,所以结果一样
-----------------
一点也不奇怪...传统的铸剑工艺不止要求工匠掌握铸造技术,更需要对冶铁、采矿、甚至烧炭和取水等庞杂而繁复的“底层”技术精通才行...所以他们可以打造出精良的刀剑,但生产力却极其低下...类似的,很多古老绝技早已或濒临失传...不是不能传承,这是市场的选择...现代工业的根本是社会分工...如果你要生产刀剑你不需要去管冶铁、更不必去管采矿,只要对其有必要的了解即可...在设计生产线时你只需要清楚哪里该用几号钢哪里改用什么设备,这些钢材和设备从哪里采购...当你专注于这些钢材是从哪座铁矿开采、钢材冶炼工艺如何时,显然你入错行了....NET也好Java也好都是应用系统大规模生产流水线...过度关注底层不说是走火入魔至少是误入歧途...如果你真的很喜欢研究底层你该去研究编译器去做类似Mono的开发而不是应用这些平台...
a.Method();
IMyInterface2 b = new MyClass();
b.Method2(); MyClass c = new MyClass();
c.Method();
c.Method2(); 红色的多