一个类实现了多个接口中的方法,在实际应用中是用类来调用方法?,还是用接口来调用方法?
代码如下:
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,我的问题是,类的地址传给了接口,这样的隐式转换没问题吗?我只看到过,继承类可以隐式地转换给基类... ...

解决方案 »

  1.   

    实际应用中,是红色的使用的多,还是天蓝色的使用的多?,使用这两种方法技术上的称呼叫什么? 
    还有 
                IMyInterface a = new MyClass(); 
                a.Method(); 
    这段代码,听大牛们说,new是创建了一个引用,把地址传给了a,我的问题是,类的地址传给了接口,这样的隐式转换没问题吗?我只看到过,继承类可以隐式地转换给基类... ...
    ============================================================
    红色的使用多还是蓝色的使用的,这里要根据具体情况,看你实例化类偏重于哪种情况。技术上的称呼不好回答。
    如果非要说:第一种是:实例化实现了这个接口的类。 第二中是实例化一个类,这个类实现了两个接口。IMyInterface a = new MyClass(); 
    接口是不能实例化的,只能实例化实现了这个接口的类。隐式转换是没有问题的。
      

  2.   

    一般红色部分用得多,将子类对象的引用传给父类引用的变量就是实现多态的方法了,是面向对象的重要思想。在这里可以将接口看成是一个纯抽象类,其实实现它的类跟它也是继承关系,它们之间也可以看成是"is a"关系。
    只是接口更强调的是对外部提供了那些操作,继承它的类一定要实现它的方法,所以你知道如果一个类继承了一个接口的话,那么
    这个类一定提供了接口中声明的方法的实现。你可以将接口看成是提供了一种标准,比如客户提出一个标准,只要我给出满足这个标准的插件,就一定能在客户的程序中正常使用。
      

  3.   


    基本上,那个大牛们是看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;对毫不相干的类型的对象进行强制类型转换。
      

  4.   

    如果你打印    x.GetHashCode();
        y.GetHashCode();
        a.GetHashCode();
        b.GetHashCode();
        c.GetHashCode();
        d.GetHashCode();你会发现是完全一样的。有人说,如果类型B继承自A,那么B的实例中就有一个私有对象指向内部的一个A类型的对象,这是错误的结论,则往往给你带到错误的概念上去推理。在多年以前某些c++的书籍作者是这样写的,甚至某些c++实现也真的是那样实现的,但是这是一个对继承的误解。至少在.net中,并不是这样的。
      

  5.   

    那个大牛们是看c入门书走火入门了,所以生搬硬套地说.net的对象是地址  -->  那个大牛们是看c++入门书走火入魔了,所以生搬硬套地说.net的对象是地址
      

  6.   

    ----------------------------------------------------
    不能赞同这样的观点,要了解基本原理就要了解本质,归根结底程序还是对内存块的操作,了解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的引用变量的引用传给了形参,此时的形参相当于引用的引用,即指针的指针,所以此时声明一个新对象并将其引用赋给形参会影响到实参,而同样的操作用值传递就不会影响到实参
    此时相当于
    形参------->实参--------->堆中的数据结构 
      

  7.   

    C#的核心仍然是C++
    CLR也只不过是运行在宿主进程上的一个软件层罢了,归根结底程序运行的机制是相同的,只不过C#是类型安全的而且不允许
    使用指针罢了,但是通过标记标记unsafe仍然可以使用指针C++是源头啊,源头啊,源头啊,源头啊(回想1万遍啊1万遍)
    就如同汇编是老祖宗啊老祖宗
    就如同其实都是机器码啊机器码以上,就是不喜欢看见有人说C++是什么走火入魔阿门
      

  8.   

    --------------------
    知道为什么这6个操作返回相同的值么,因为这6个引用变量指向的都是同一个对象
    还有什么相同的地址不同的对象,大哥。既然是相同的地址,那就是同一个对象。我也不知道说你什么好了
    见图
    x------>堆中的对象
    y---|
    a---|
    b---|
    c---|
    d---|
    “.”操作是作用在对象上的
    可以写程序证明这6个引用变量本身的地址是不同的
             
      

  9.   

    晕!我也来说两句:面向接口编程,请尽量配合工厂模式或依赖注入等模式,不要在客户类里面new接口的实现类原因: 那样的话,两个类之间仍然是紧耦合的,并没有起到松耦合的作用,没有达到面向接口编程的目的
      

  10.   

    晕!晕! 上个回复没看其他回帖,原来在打架了!
    关于对象、地址和引用变量,再次表明立场: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的开闭原则,是个大事了。
    请查阅设计模式的工厂模式和依赖注入模式,会对你理解这些有所帮助,找到使用接口及其实现类的正确方法。
      

  11.   

    引用MSDN中说明:类或结构定义的作用类似于蓝图,指定该类型可以进行哪些操作。从本质上说,对象是按照此蓝图分配和配置的内存块。程序可以创建同一个类的多个对象。对象也称为实例,可以存储在命名变量中,也可以存储在数组或集合中。使用这些变量来调用对象方法及访问对象公共属性的代码称为客户端代码。参见MSDN:
    http://msdn.microsoft.com/zh-cn/library/ms173110.aspx
      

  12.   

    另外一篇:
    http://msdn.microsoft.com/zh-cn/library/x9afc042.aspx自己看看,应该就明白了
      

  13.   

    没有必要在字眼上扣的太死,看看e文的MSDNhttp://msdn.microsoft.com/en-us/library/ms173110.aspxBecause classes are reference types, a variable of a class object holds a reference to the address of the object on the managed heap. If a second object of the same type is assigned to the first object, then both variables refer to the object at that address. This point is discussed in more detail later in this topic. 所以你可以说x、y、a、b、c都是同一个对象,因为这些变量都引用同一托管堆地址上的对象也有人习惯说x、y、a、b、c是同一个对象的引用,它们指向同一个对象new MyClass()
      

  14.   

    同意sp123和amandag在C#中不要玩什么地址的概念,除非你要写非托管代码、unsafe代码,对象就是对象,x、y、a、b、c他就是同一个对象。至于是“用类来调用方法还是用接口来调用方法”,这一是要看你是怎么实现的,如果显示实现接口方法,那只能通过接口来调用,而如果是隐式实现,像楼主写的那样的,那既可以用类也可以用接口来调用。二是要看你调用的地方的需要,这就是上面有人说的这模式那模式的了,对于这些,我的观点是应用为王,能满足你的需要的就是合适的,而为了模式而模式的,那就是舍本逐末了。另外,摘录一下msdn中关于ref的:
    ref 关键字使参数按引用传递。其效果是,当控制权传递回调用方法时,在方法中对参数的任何更改都将反映在该变量中。若要使用 ref 参数,则方法定义和调用方法都必须显式使用 ref 关键字。
    按引用传递值类型是有用的,但是 ref 对于传递引用类型也是很有用的。这允许被调用的方法修改该引用所引用的对象,因为引用本身是按引用来传递的。
      

  15.   

    无本质区别,那位大牛实际说的也没错实际上一个对象在内存里除了入口地址、代码内容,还有方法表。你的问题实际上就是对方法表的理解程度,方法表实际上表示的是各方法相对入口地址的偏移量而继承本身的实质就是继承父类的方法表。public class MyClass : IMyInterface, IMyInterface2 
        { 
            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本身
          
      

  16.   

    http://book.csdn.net/bookfiles/684/10068421446.shtml
      

  17.   

    http://book.csdn.net/bookfiles/684/10068421441.shtml
      

  18.   

    学习
    其实我想说的就是,x、y、a、b、c并不是对象,而是对象的引用,只是引用了同一个对象
    有时候这种错误的说法还是很误导新人的
      

  19.   

    回头又仔细看几遍sp1234的意见,应该说,他的意思或许也没有错。老实说,我承认没太看得懂,感觉在表达上有点容易引起误会。另外,很奇怪sp1234为何这么反感在C#中使用地址及引用来描述对象及其相关变量,全部使用对象一词能够说清楚这些破事么?引用MSDN: http://msdn.microsoft.com/zh-cn/library/ms173110.aspx由于类是引用类型,因此类对象的变量引用该对象在托管堆上的地址。如果将同一类型的第二个对象分配给第一个对象,则两个变量都引用该地址的对象。这一点将在本主题后面部分进行更详细的讨论。 
    ----------------引用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类中的相关成员。
    欢迎大家批评,如有人想继续讨论此话题,我来开个贴,向大家再学习学习。就不影响楼主此贴的主旨了。
      

  20.   

     
     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方法表里那个偏移量处指向的是同一个地址,所以结果一样
      

  21.   

    已开贴讨论争论问题所在,请大家移步继续http://topic.csdn.net/u/20090228/22/2ae369ec-2531-44ad-9c0e-d3b7ed1658d5.html
      

  22.   

    另外,很奇怪sp1234为何这么反感在C#中使用地址及引用来描述对象及其相关变量,全部使用对象一词能够说清楚这些破事么?
    -----------------
    一点也不奇怪...传统的铸剑工艺不止要求工匠掌握铸造技术,更需要对冶铁、采矿、甚至烧炭和取水等庞杂而繁复的“底层”技术精通才行...所以他们可以打造出精良的刀剑,但生产力却极其低下...类似的,很多古老绝技早已或濒临失传...不是不能传承,这是市场的选择...现代工业的根本是社会分工...如果你要生产刀剑你不需要去管冶铁、更不必去管采矿,只要对其有必要的了解即可...在设计生产线时你只需要清楚哪里该用几号钢哪里改用什么设备,这些钢材和设备从哪里采购...当你专注于这些钢材是从哪座铁矿开采、钢材冶炼工艺如何时,显然你入错行了....NET也好Java也好都是应用系统大规模生产流水线...过度关注底层不说是走火入魔至少是误入歧途...如果你真的很喜欢研究底层你该去研究编译器去做类似Mono的开发而不是应用这些平台...
      

  23.   

        IMyInterface a = new MyClass(); 
                a.Method(); 
                IMyInterface2 b = new MyClass(); 
                b.Method2(); 
                MyClass c = new MyClass(); 
                c.Method(); 
                c.Method2(); 
    红色的多