none
本人学习 C# 编程才一、二天有些疑问,向高手求解。 RRS feed

  • 问题

  • 本人学习 C# 编程才一、二天有些疑问,向高手求解!(下文所提出的问题并非特指 C# 在其它语言中也是存在的)

    疑问一:编译器对重载方法,怎么不单独区分静态方法和实例方法?

    如:

    // 例一(假设类名是 ClassA)

    public void Method(params string[] values) {}

    public static void Method(string value) {} // 更正:Method(object value) 不是 Method(string value); 

    调用方式:
    ClassA.Method("123"); // error 编译错误

    注:其实此处“类名.方法名”的方式明显指定了调用的是静态方法,但编译器却认为你想调用的是实例级方法 void Method(params string[])

    // 例二:

    public void Method(string value) {}

    public static void Method(string value) {}

    注:编译错误,其实两者完全可与区分,没有二义性(如:this.Method类名.Method)。如果编译器能将 static 关键字作为重载依据就好了

    另:如果方法中存在 params 参数,则 C# 编译器定位重载版本不够精确(加上 params 参数,的确是二义性增加,但有不少情况还是可以被精确定位,但 C# 编译器定位很不理想)



    疑问二:
    为什么不能增加代表父类型和当前类型的关键字?

    basethis 关键分别代表父类型实例和当前类型实例,如果能在添加两个关键字表示父类型和当前类型就好了(当然不是必须的)。

    public class 未知的类名

    {

        public static int a = 1;

        public static void Method()

        {

            int a = 2;

            // 此处因为类名未知,所以无法访问类静态变量 a

        }  

    }

    * 以上示例似乎不太合理(如:方法里面的 a 改个名字不就行了?),在这里为了描述清楚仅仅例子而已,实际情形会很复杂。

    * 为什么类名会未知?如在 ASP.NET *.aspx 文件(注:这里特指非代码后置的,也就是说没有 *.cs 文件的 *.aspx)类名就是由编译器生成的,在这个页面里面写代码,就会面临上述问题。



    疑问三:
    属性为什么不能单独对 getset 进行虚拟化?

    如果定义 virtual 关键字,则整个属性(指 getset 都有的)都是虚拟化的 getset 一起被重写了,我们知道属性编译后就是两个 get_set_ 打头的方法,为什么能单独给 getset

    加访问修饰符,而不能单独对 getset 增加 virtual 关键字呢?

    public string MyValue

    {

        get { return null; }

        protected set { }      // 可以单独指定访问修饰符

    }

    // get 不想被子类重写,只想子类重写 set 的方式不可以了(除非单独在定义方法了,这样破坏了优美和简洁)

    public string MyValue

    {

        get { return null; }

        virtual set { }    // 单独指定 virtual 就不可以了

    }




    疑问四:
    接口成员不能定义访问修饰符(都是 public 的)?

    Java 论坛看过别人讨论接口成员为什么不能是 protected,其理由我觉得还是很牵强(扯一堆编程思想上的逻辑问题,根本不能令我信服),我觉得接口允许 protected 成员没什么问题而且更好的体现了封装性,也不存在逻辑矛盾,本人觉得就是语言支不支持的问题而已。

    (如同 return 为什么不能返回多个值一样,不存在逻辑矛盾问题,只要语言支持就完全可以,据我所知:e语言支持)

    如:

    public interface MyInterface

    {

        protected void MyMethod();

    }

    * 表示实现上述接口的类型,必然存在一个 protected 修饰的 MyMethod 方法,这样有什么不可吗?

    * 该接口除了约束方法签名,还约束了访问修饰符(只是这个方法对实例控制者而言是不可见的),这样有什么不可吗?

    * 讨论到这个问题时,有很多烂仔会说你编程经验太少了... 编程思想有问题... 等等,给我打住!说实际的。





    • 已编辑 大笨虫 2012年3月8日 12:10 更正一处错误。
    2012年3月8日 5:44

答案

  • 首先,第一问你没有错误,至少我无法重现你的错误,代码如下:

    namespace MyTest
    {
        public class A
        {
            class Program
            {
                public void Method(params string[] values) { }

                public static void Method(string value) { }

                static void Main(string[] args)
                {
                    Program.Method("aa");
                }
            }
        }
    }

    后面一些疑问我也无能为力解答,不过看上去貌似不错哦,你可以去微软反馈中心反馈,以便今后在C#中进行语言特性的改进:http://connect.microsoft.com/


       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    • 已建议为答案 Jacky_shen 2012年3月8日 8:03
    • 已标记为答案 大笨虫 2012年3月10日 7:58
    2012年3月8日 6:30
    版主
  • 1,如Wei_Dong所说,不再赘述。

    2,       知道reflection吗?

                 获取父类成员值

                FieldInfo PField = this.GetType().BaseType.GetField("b1");
                object PFieldV = PField.GetValue(this);

               获取当前类成员值

                FieldInfo ZField = this.GetType().GetField("a");
                object ZFieldV = ZField.GetValue(this);

    3 ,

    4,interface 的目的就是提供一种contract,一种承诺,我能提供什么什么功能,如果你给它加protected,那你不是让它对client“食言”嘛。






    • 已编辑 Jacky_shen 2012年3月8日 11:46
    • 已标记为答案 大笨虫 2012年3月10日 7:58
    2012年3月8日 7:59
  • Hi Jack:)

    你的第二个回答用this……是针对疑问2吧?貌似静态函数中不允许用this的……


       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    2012年3月8日 8:03
    版主
  • Hey Jack,你觉得他的这些语言新特性设计如何?我觉得还可以啊……你也发表一下意见看看(指出其优势和不足)。大家讨论嘛,正确错误都有可能的……让我们晒晒自己呗……:-)

       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    • 已标记为答案 大笨虫 2012年3月10日 7:58
    2012年3月8日 8:06
    版主
  • Hi WeiDong,

    跟我还那么客气啊:-)

    你说的没错, 如果字静态方法中可以用下面的

    FieldInfo PField = MethodBase.GetCurrentMethod().DeclaringType.BaseType.GetField("b1");
    object PFieldV = PField.GetValue(null );


      FieldInfo ZField = MethodBase.GetCurrentMethod().DeclaringType.GetField("a");
    object ZFieldV = ZField.GetValue(null );

    2012年3月8日 8:17
  • Hey Jack,你觉得他的这些语言新特性设计如何?我觉得还可以啊……你也发表一下意见看看(指出其优势和不足)。大家讨论嘛,正确错误都有可能的……让我们晒晒自己呗……:-)

       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    第3个问题,不清楚:)

    第4个问题,接口的初衷就是公开自己的一切,如果想隐藏某些东西,那就用abstract class。





    • 已编辑 Jacky_shen 2012年3月8日 11:47
    • 已标记为答案 大笨虫 2012年3月10日 7:57
    2012年3月8日 8:33
  • 对呀,接口的特性就是对client全裸,想犹抱琵琶半遮面的就用abstract class。关于设计的问题啊,这个没有标准的答案,有得争了。

    • 已编辑 Jacky_shen 2012年3月8日 13:37
    • 已标记为答案 大笨虫 2012年3月10日 7:57
    2012年3月8日 13:19
  • abstract  不能多继承,如果 abstract 可以多继承那么 interface 就没有存在的理由,就像 c++ 里面,绝不会搞个接口出来。

    interface 是一个标准规范,任何继承他的类别都必须强制实作它的方法/属性,在OO的观念里,method都是用interface 来定义,所以interface 很象一个小单位,不会不小心就让你的class肥肿,用了interface 能让你的架构设计耦合度降低

    abstract class可以是规范也可以不是规范,任何继承他的类别都不一定要实作它的方法/属性,因为它还是很接近一般的Class,在OO观念里若他能多继承,那肯定会让class肥大且难以维护因为耦合度太高。

    语言会进化,表示设计者看到了C++的缺点,才会进化成java/c#,让进化的语言更接近OO。

    像我自己的习惯,我会将功能定义在interface ,然后abstract class继承需要interface,并且实做这些method ,然后class在继承abstract class,这样的写法很容易进行抽换IoC,这必须熟读设计模式才能自己体悟,没有一种模式可以一招打遍天下无敌手,建议你可以拜读程杰的"大话设计模式"秦小波的"设计模式之禅"。


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/


    2012年3月9日 5:26
  • abstract  不能多继承,如果 abstract 可以多继承那么 interface 就没有存在的理由,就像 c++ 里面,绝不会搞个接口出来。

    interface 是一个标准规范,任何继承他的类别都必须强制实作它的方法/属性,在OO的观念里,method都是用interface 来定义,所以interface 很象一个小单位,不会不小心就让你的class肥肿,用了interface 能让你的架构设计耦合度降低

    abstract class可以是规范也可以不是规范,任何继承他的类别都不一定要实作它的方法/属性,因为它还是很接近一般的Class,在OO观念里若他能多继承,那肯定会让class肥大且难以维护因为耦合度太高。

    语言会进化,表示设计者看到了C++的缺点,才会进化成java/c#,让进化的语言更接近OO。

    像我自己的习惯,我会将功能定义在interface ,然后abstract class继承需要interface,并且实做这些method ,然后class在继承abstract class,这样的写法很容易进行抽换IoC,这必须熟读设计模式才能自己体悟,没有一种模式可以一招打遍天下无敌手,建议你可以拜读程杰的"大话设计模式"秦小波的"设计模式之禅"。


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/



    我觉得其理由牵强,而且和设计模式基本不沾边,我通常所说的设计模式是基于 OO 之上的,而我所谈的只是 OO 部分或者说 OO 机制(位于设计模式之下)。
    接口方法可以指定 protected 访问修饰,一不违背里氏替换也不违背“扩展开放,修改封闭”的原则,有何不可呢?

    另外你所说的:
    “interface 是一个标准规范,任何继承他的类别都必须强制实作它的方法/属性 ...(略很多字).... abstract class可以是规范也可以不是规范,任何继承他的类别都不一定要实作它的方法/属性”。
    我想告诉你:不好意思,你说错了!按你的推论,我也可以说 interface 不是不规范的,其它类不一定要实现它的方法,请见下面例子:

    例子一(抽象类):

    public abstract class MyBaseClass
    {
         public abstract void MyMethod();
    }

    public abstract class MyChildClass : MyBaseClass
    {  }

    // 我想这就是你说的“不一定要实现它的方法”所指的例外情形吧?否则不可能存在你所说的“不一定”!

    例子二(接口):

    public interface MyInterface
    {
        void MyMethod();
    }

    public abstract class MyAbstractClass : MyInterface
    {
        public abstract void MyMethod();   // 在抽象类中,如果申明为抽象的方法,则可以不去具体实现
    }

    // 按你所说的逻辑而言,接口根本算不上你所说的“强制”实现了。

    dear

    照您的实例我反驳:

    1.abstract class里的method不一定要宣告成abstract method,这就是我说的不一定要遵守,再method里把abstract 拿掉就好。

    2.对于abstract class而言,他已经实作interface的规范了,若对于继承abstract class而言它还是必须要实作abstract method。

    这两个实例,你要这样讲也可以,在我看来这只是为了反对而反对,在玩文字游戏罢了。

    的确,C++里用protected,可以解决你所讲的原则,但弹性如何?我不清楚

    http://blog.codingnow.com/2010/03/cpp_protected.html

    http://blog.csdn.net/feiyinzilgd/article/details/6226348

    再套剧楼上说的话,设计没有标准的答案,全得看当时后的情况。

    你也可直接跟MS反应你的想法http://connect.microsoft.com/

    目前就只能尊守C#的规则来走,老实讲,我也有跟你一样的疑问,尤其是疑问4。


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/



    2012年3月9日 10:17
  • 楼主请稍安勿躁……额……余小章是来自港澳台地区的,可能用语方式略有不同,请谅解。

    至于你说的问题,我之前也说过,确实不错(我个人认为:微软目前只是采取主流的一种做法,当然,任何做法都有优点缺点,你所说的可能会弥补OOP的缺陷,但是也有可能带来其它意想不到的负面作用……)。建议你直接去论坛反馈:http://connect.microsoft.com/,谢谢!!

    一般来说:接口的定义就是“契约”,里边的方法必须是公开的;而抽象类更接近类——这是早先OOP定义的原则,没有理由的。
    当然,你若提出更好的设计原则和理由,建议去微软反映,我们也是没有办法的,呵呵!


       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    • 已标记为答案 大笨虫 2012年3月10日 7:58
    2012年3月10日 5:00
    版主
  • dear

    你完全误会我的意思了,

    1.abstract class里的method不一定要宣告成abstract method,这就是我说的不一定要遵守,再method里把abstract 拿掉就好。
    2.对于abstract class而言,他已经实作interface的规范了,若对于继承abstract class而言它还是必须要实作abstract method。
    ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
    这两句跟protected完全无关的,应该是我文章段落没排好,让你误会了,我指的C++里的情况,这是关于C++里的protected,我只把搜寻到的状况分享出来而已,这两句主要想要表达的是目前.NET的语言规范用法,延续上面1,2,我用别的说法,让您参考看看
    1.继承abstract class的class不一定要实现abstract class里的member,因为在abstract class里的member它可以 使用或不使用 abstract关键字。
    2.凡继承interface的class只要写了跟interface相同名称的 member,就算只有壳,里面不写实现过程,在CLR里就算是实现,至少不会出现错误。

    目前就只能尊守C#的规则来走,老实讲,我也有跟你一样的疑问,尤其是疑问4。
    ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
    这句代表我跟你有相同的困惑,因为我也想要写出非公开的规范,让内部的设计师使用


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/

    • 已标记为答案 大笨虫 2012年3月14日 3:09
    2012年3月10日 15:04
  • 楼主请稍安勿躁……额……余小章是来自港澳台地区的,可能用语方式略有不同,请谅解。

    至于你说的问题,我之前也说过,确实不错(我个人认为:微软目前只是采取主流的一种做法,当然,任何做法都有优点缺点,你所说的可能会弥补OOP的缺陷,但是也有可能带来其它意想不到的负面作用……)。建议你直接去论坛反馈:http://connect.microsoft.com/,谢谢!!

    一般来说:接口的定义就是“契约”,里边的方法必须是公开的;而抽象类更接近类——这是早先OOP定义的原则,没有理由的。
    当然,你若提出更好的设计原则和理由,建议去微软反映,我们也是没有办法的,呵呵!


       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处


    其实问题的本质就是我所要质疑这个必须要公开的“契约”,不尽人意也不尽合理吗,呵呵。

    这里就存在这样的一个问题,这个“契约”谁定的?定这个“契约”时是不是遗漏了点东西?这个“契约”我们应该不应该质疑?而不应该因为是“契约”就应该推倒一切合理要求~~~~ 如果没有强有力的理由推到 protected 那么这个“契约”就是有残缺的、不完善的部分。

    关于 protected 讨论总结如下:

    1)强制、实作 ---- 不是理由,也不违反(接口有 protected 还是要强制实作的)。

    2)违背承诺 ----- 没有违背,站在实例控制者角度上接口没有承诺 protected 方法(实例控制者看不见 protected 方法),也就是说 protected 就相当于接口专门针对子类做承诺(而不是对实例控制者的承诺),而 public 成员是对子类和实例控制者的共同承诺。

    3)设计模式 ----- 设计模式有很多,通常所说的是基于 OO 的设计模式,OO 是在设计模式之下。上述问题属于 OO 部分,而与设计模式无关(可能会影响到现有设计模式)。

    2012年3月15日 3:39

全部回复

  • 首先,第一问你没有错误,至少我无法重现你的错误,代码如下:

    namespace MyTest
    {
        public class A
        {
            class Program
            {
                public void Method(params string[] values) { }

                public static void Method(string value) { }

                static void Main(string[] args)
                {
                    Program.Method("aa");
                }
            }
        }
    }

    后面一些疑问我也无能为力解答,不过看上去貌似不错哦,你可以去微软反馈中心反馈,以便今后在C#中进行语言特性的改进:http://connect.microsoft.com/


       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    • 已建议为答案 Jacky_shen 2012年3月8日 8:03
    • 已标记为答案 大笨虫 2012年3月10日 7:58
    2012年3月8日 6:30
    版主
  • 1,如Wei_Dong所说,不再赘述。

    2,       知道reflection吗?

                 获取父类成员值

                FieldInfo PField = this.GetType().BaseType.GetField("b1");
                object PFieldV = PField.GetValue(this);

               获取当前类成员值

                FieldInfo ZField = this.GetType().GetField("a");
                object ZFieldV = ZField.GetValue(this);

    3 ,

    4,interface 的目的就是提供一种contract,一种承诺,我能提供什么什么功能,如果你给它加protected,那你不是让它对client“食言”嘛。






    • 已编辑 Jacky_shen 2012年3月8日 11:46
    • 已标记为答案 大笨虫 2012年3月10日 7:58
    2012年3月8日 7:59
  • Hi Jack:)

    你的第二个回答用this……是针对疑问2吧?貌似静态函数中不允许用this的……


       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    2012年3月8日 8:03
    版主
  • Hey Jack,你觉得他的这些语言新特性设计如何?我觉得还可以啊……你也发表一下意见看看(指出其优势和不足)。大家讨论嘛,正确错误都有可能的……让我们晒晒自己呗……:-)

       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    • 已标记为答案 大笨虫 2012年3月10日 7:58
    2012年3月8日 8:06
    版主
  • Hi WeiDong,

    跟我还那么客气啊:-)

    你说的没错, 如果字静态方法中可以用下面的

    FieldInfo PField = MethodBase.GetCurrentMethod().DeclaringType.BaseType.GetField("b1");
    object PFieldV = PField.GetValue(null );


      FieldInfo ZField = MethodBase.GetCurrentMethod().DeclaringType.GetField("a");
    object ZFieldV = ZField.GetValue(null );

    2012年3月8日 8:17
  • Hey Jack,你觉得他的这些语言新特性设计如何?我觉得还可以啊……你也发表一下意见看看(指出其优势和不足)。大家讨论嘛,正确错误都有可能的……让我们晒晒自己呗……:-)

       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    第3个问题,不清楚:)

    第4个问题,接口的初衷就是公开自己的一切,如果想隐藏某些东西,那就用abstract class。





    • 已编辑 Jacky_shen 2012年3月8日 11:47
    • 已标记为答案 大笨虫 2012年3月10日 7:57
    2012年3月8日 8:33
  • 不好意思我写错代码了:

    class Program
            {
                public void Method(params string[] values) { }

                public static void Method(object value) { }  // 此处是 object 不是 string 编译绝对报错

                static void Main(string[] args)
                {
                    Program.Method("aa");
                }
            }

    • 已标记为答案 大笨虫 2012年3月10日 7:57
    • 取消答案标记 大笨虫 2012年3月14日 3:10
    2012年3月8日 12:08
  • 用反射,针对第 2 个题目就没有意义了,我所说的是编译机制方面,不需要动态获取。

    没有对 client 食言...... 相当于对 client 做出承诺你可以继承访问,但你不能直接访问。如果不考虑到多继承,我宁愿用抽象类,因为可以有 protected virtual

    • 已标记为答案 大笨虫 2012年3月10日 7:57
    • 取消答案标记 大笨虫 2012年3月14日 3:09
    2012年3月8日 12:15
  • 我的问题可不是在静态方法中用 this、base 关键字哦。

    我是指 C# 提供一种新的关键字来表示类型,比如:baseclass 表示当前的父类型 myclass 表示当前的类型

    • 已标记为答案 大笨虫 2012年3月10日 7:57
    • 取消答案标记 大笨虫 2012年3月14日 3:09
    2012年3月8日 12:16
  • abstract  不能多继承,如果 abstract 可以多继承那么 interface 就没有存在的理由,就像 c++ 里面,绝不会搞个接口出来。
    • 已标记为答案 大笨虫 2012年3月10日 7:57
    • 取消答案标记 大笨虫 2012年3月10日 7:58
    2012年3月8日 12:18
  • 对呀,接口的特性就是对client全裸,想犹抱琵琶半遮面的就用abstract class。关于设计的问题啊,这个没有标准的答案,有得争了。

    • 已编辑 Jacky_shen 2012年3月8日 13:37
    • 已标记为答案 大笨虫 2012年3月10日 7:57
    2012年3月8日 13:19
  • abstract  不能多继承,如果 abstract 可以多继承那么 interface 就没有存在的理由,就像 c++ 里面,绝不会搞个接口出来。

    interface 是一个标准规范,任何继承他的类别都必须强制实作它的方法/属性,在OO的观念里,method都是用interface 来定义,所以interface 很象一个小单位,不会不小心就让你的class肥肿,用了interface 能让你的架构设计耦合度降低

    abstract class可以是规范也可以不是规范,任何继承他的类别都不一定要实作它的方法/属性,因为它还是很接近一般的Class,在OO观念里若他能多继承,那肯定会让class肥大且难以维护因为耦合度太高。

    语言会进化,表示设计者看到了C++的缺点,才会进化成java/c#,让进化的语言更接近OO。

    像我自己的习惯,我会将功能定义在interface ,然后abstract class继承需要interface,并且实做这些method ,然后class在继承abstract class,这样的写法很容易进行抽换IoC,这必须熟读设计模式才能自己体悟,没有一种模式可以一招打遍天下无敌手,建议你可以拜读程杰的"大话设计模式"秦小波的"设计模式之禅"。


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/


    2012年3月9日 5:26
  • abstract  不能多继承,如果 abstract 可以多继承那么 interface 就没有存在的理由,就像 c++ 里面,绝不会搞个接口出来。

    interface 是一个标准规范,任何继承他的类别都必须强制实作它的方法/属性,在OO的观念里,method都是用interface 来定义,所以interface 很象一个小单位,不会不小心就让你的class肥肿,用了interface 能让你的架构设计耦合度降低

    abstract class可以是规范也可以不是规范,任何继承他的类别都不一定要实作它的方法/属性,因为它还是很接近一般的Class,在OO观念里若他能多继承,那肯定会让class肥大且难以维护因为耦合度太高。

    语言会进化,表示设计者看到了C++的缺点,才会进化成java/c#,让进化的语言更接近OO。

    像我自己的习惯,我会将功能定义在interface ,然后abstract class继承需要interface,并且实做这些method ,然后class在继承abstract class,这样的写法很容易进行抽换IoC,这必须熟读设计模式才能自己体悟,没有一种模式可以一招打遍天下无敌手,建议你可以拜读程杰的"大话设计模式"秦小波的"设计模式之禅"。


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/



    我觉得其理由牵强,而且和设计模式基本不沾边,我通常所说的设计模式是基于 OO 之上的,而我所谈的只是 OO 部分或者说 OO 机制(位于设计模式之下)。
    接口方法可以指定 protected 访问修饰,一不违背里氏替换也不违背“扩展开放,修改封闭”的原则,有何不可呢?

    另外你所说的:
    “interface 是一个标准规范,任何继承他的类别都必须强制实作它的方法/属性 ...(略很多字).... abstract class可以是规范也可以不是规范,任何继承他的类别都不一定要实作它的方法/属性”。
    我想告诉你:不好意思,你说错了!按你的推论,我也可以说 interface 不是不规范的,其它类不一定要实现它的方法,请见下面例子:

    例子一(抽象类):

    public abstract class MyBaseClass
    {
         public abstract void MyMethod();
    }

    public abstract class MyChildClass : MyBaseClass
    {  }

    // 我想这就是你说的“不一定要实现它的方法”所指的例外情形吧?否则不可能存在你所说的“不一定”!

    例子二(接口):

    public interface MyInterface
    {
        void MyMethod();
    }

    public abstract class MyAbstractClass : MyInterface
    {
        public abstract void MyMethod();   // 在抽象类中,如果申明为抽象的方法,则可以不去具体实现
    }

    // 按你所说的逻辑而言,接口根本算不上你所说的“强制”实现了。

    • 已标记为答案 大笨虫 2012年3月10日 7:57
    • 取消答案标记 大笨虫 2012年3月14日 3:09
    2012年3月9日 8:21
  • abstract  不能多继承,如果 abstract 可以多继承那么 interface 就没有存在的理由,就像 c++ 里面,绝不会搞个接口出来。

    interface 是一个标准规范,任何继承他的类别都必须强制实作它的方法/属性,在OO的观念里,method都是用interface 来定义,所以interface 很象一个小单位,不会不小心就让你的class肥肿,用了interface 能让你的架构设计耦合度降低

    abstract class可以是规范也可以不是规范,任何继承他的类别都不一定要实作它的方法/属性,因为它还是很接近一般的Class,在OO观念里若他能多继承,那肯定会让class肥大且难以维护因为耦合度太高。

    语言会进化,表示设计者看到了C++的缺点,才会进化成java/c#,让进化的语言更接近OO。

    像我自己的习惯,我会将功能定义在interface ,然后abstract class继承需要interface,并且实做这些method ,然后class在继承abstract class,这样的写法很容易进行抽换IoC,这必须熟读设计模式才能自己体悟,没有一种模式可以一招打遍天下无敌手,建议你可以拜读程杰的"大话设计模式"秦小波的"设计模式之禅"。


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/



    我觉得其理由牵强,而且和设计模式基本不沾边,我通常所说的设计模式是基于 OO 之上的,而我所谈的只是 OO 部分或者说 OO 机制(位于设计模式之下)。
    接口方法可以指定 protected 访问修饰,一不违背里氏替换也不违背“扩展开放,修改封闭”的原则,有何不可呢?

    另外你所说的:
    “interface 是一个标准规范,任何继承他的类别都必须强制实作它的方法/属性 ...(略很多字).... abstract class可以是规范也可以不是规范,任何继承他的类别都不一定要实作它的方法/属性”。
    我想告诉你:不好意思,你说错了!按你的推论,我也可以说 interface 不是不规范的,其它类不一定要实现它的方法,请见下面例子:

    例子一(抽象类):

    public abstract class MyBaseClass
    {
         public abstract void MyMethod();
    }

    public abstract class MyChildClass : MyBaseClass
    {  }

    // 我想这就是你说的“不一定要实现它的方法”所指的例外情形吧?否则不可能存在你所说的“不一定”!

    例子二(接口):

    public interface MyInterface
    {
        void MyMethod();
    }

    public abstract class MyAbstractClass : MyInterface
    {
        public abstract void MyMethod();   // 在抽象类中,如果申明为抽象的方法,则可以不去具体实现
    }

    // 按你所说的逻辑而言,接口根本算不上你所说的“强制”实现了。

    dear

    照您的实例我反驳:

    1.abstract class里的method不一定要宣告成abstract method,这就是我说的不一定要遵守,再method里把abstract 拿掉就好。

    2.对于abstract class而言,他已经实作interface的规范了,若对于继承abstract class而言它还是必须要实作abstract method。

    这两个实例,你要这样讲也可以,在我看来这只是为了反对而反对,在玩文字游戏罢了。

    的确,C++里用protected,可以解决你所讲的原则,但弹性如何?我不清楚

    http://blog.codingnow.com/2010/03/cpp_protected.html

    http://blog.csdn.net/feiyinzilgd/article/details/6226348

    再套剧楼上说的话,设计没有标准的答案,全得看当时后的情况。

    你也可直接跟MS反应你的想法http://connect.microsoft.com/

    目前就只能尊守C#的规则来走,老实讲,我也有跟你一样的疑问,尤其是疑问4。


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/



    2012年3月9日 10:17
  • abstract  不能多继承,如果 abstract 可以多继承那么 interface 就没有存在的理由,就像 c++ 里面,绝不会搞个接口出来。

    interface 是一个标准规范,任何继承他的类别都必须强制实作它的方法/属性,在OO的观念里,method都是用interface 来定义,所以interface 很象一个小单位,不会不小心就让你的class肥肿,用了interface 能让你的架构设计耦合度降低

    abstract class可以是规范也可以不是规范,任何继承他的类别都不一定要实作它的方法/属性,因为它还是很接近一般的Class,在OO观念里若他能多继承,那肯定会让class肥大且难以维护因为耦合度太高。

    语言会进化,表示设计者看到了C++的缺点,才会进化成java/c#,让进化的语言更接近OO。

    像我自己的习惯,我会将功能定义在interface ,然后abstract class继承需要interface,并且实做这些method ,然后class在继承abstract class,这样的写法很容易进行抽换IoC,这必须熟读设计模式才能自己体悟,没有一种模式可以一招打遍天下无敌手,建议你可以拜读程杰的"大话设计模式"秦小波的"设计模式之禅"。


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/



    我觉得其理由牵强,而且和设计模式基本不沾边,我通常所说的设计模式是基于 OO 之上的,而我所谈的只是 OO 部分或者说 OO 机制(位于设计模式之下)。
    接口方法可以指定 protected 访问修饰,一不违背里氏替换也不违背“扩展开放,修改封闭”的原则,有何不可呢?

    另外你所说的:
    “interface 是一个标准规范,任何继承他的类别都必须强制实作它的方法/属性 ...(略很多字).... abstract class可以是规范也可以不是规范,任何继承他的类别都不一定要实作它的方法/属性”。
    我想告诉你:不好意思,你说错了!按你的推论,我也可以说 interface 不是不规范的,其它类不一定要实现它的方法,请见下面例子:

    例子一(抽象类):

    public abstract class MyBaseClass
    {
         public abstract void MyMethod();
    }

    public abstract class MyChildClass : MyBaseClass
    {  }

    // 我想这就是你说的“不一定要实现它的方法”所指的例外情形吧?否则不可能存在你所说的“不一定”!

    例子二(接口):

    public interface MyInterface
    {
        void MyMethod();
    }

    public abstract class MyAbstractClass : MyInterface
    {
        public abstract void MyMethod();   // 在抽象类中,如果申明为抽象的方法,则可以不去具体实现
    }

    // 按你所说的逻辑而言,接口根本算不上你所说的“强制”实现了。

    dear

    照您的实例我反驳:

    1.abstract class里的method不一定要宣告成abstract method,这就是我说的不一定要遵守,再method里把abstract 拿掉就好。

    2.对于abstract class而言,他已经实作interface的规范了,若对于继承abstract class而言它还是必须要实作abstract method。

    这两个实例,你要这样讲也可以,在我看来这只是为了反对而反对,在玩文字游戏罢了。

    的确,C++里用protected,可以解决你所讲的原则,但弹性如何?我不清楚

    http://blog.codingnow.com/2010/03/cpp_protected.html

    http://blog.csdn.net/feiyinzilgd/article/details/6226348

    再套剧楼上说的话,设计没有标准的答案,全得看当时后的情况。

    你也可直接跟MS反应你的想法http://connect.microsoft.com/

    目前就只能尊守C#的规则来走,老实讲,我也有跟你一样的疑问,尤其是疑问4。


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/




     

    请先原谅我说法的语气,我是比较心急和粗放的人。

    我根本不认同你的说法,等于是在胡扯,跟我扯皮胶着我原先说描述的问题。你凭什么认为 abstract 实作了?你说实作了岂不和 abstract 矛盾?那么实作了还叫什么抽象方法?!
    抽象类实现接口,可以不定义具体实现,但必须声明为抽象成员,这个仅仅属于语言机制问题。微软也可以定义为“抽象类”实现接口,无需定义,直接在抽象类中变成抽象方法,你说是不是?

    接口为什么不能有 protected 成员?

    您的反对理由总结1强制和实作”,他和 protected 有什么关系?不影响你现在的强制和实作吧?
    您的反对理由总结2耦合度”,和 protected 更不靠谱吧~~~ 耦合度没有变化啊?!

    您的其它反对理由... 不赘述,不沾边。

    总之到目前我是没有看到一条对“反对接口存在 protected 成员”具有杀伤力的理由,不仅没有杀伤力而且基本都不沾边。

    我觉得我们很多人都呈现思想僵化,因为接口从出现以来就没有访问修饰符,所以天经地义的认为:接口就不应该有 protected 修饰符,否则就是逆天行道,想尽一切办法说服(或攻击)持不同意见者。我们为什么不能用怀疑的态度,去分析这个问题呢?讨论一下 protected 修饰符带来的好处,以及可能出现的问题。

    我曾今在 Java 论坛上看过类似这样讨论,参与讨论者很多,基本上就是:
    1
    )大谈设计模式(关设计模式屁事啊,可笑之极),
    2
    )大谈OO思想,胡乱带高帽(我想过很久,找不到抵触OO地方)

    3)这样子类不能访问protected成员(是实例控制者,不是子类。符合里氏替换原则)

    很多人描述反驳理由,都是我所说的“思想僵化”情形,换个角度就想通了,原来没有抵触,就如同上面有一位网友用什么“全裸”(他全裸意思是public)的概念来反驳,这就是典型的“思想僵化”!为什么不去怀疑全裸,接口申明 private 的确没有意义,prtoected有什么不行吗?

    interface  IMy{ protected void MyMethod(); }

    IMay m = new 接口实现类(); // 用接口类型引用实例

    m.MyMethod();        // 错误。实例控制者站接口角度上也看不到 MyMethod 方法


    接口实现类 o = new 接口实现类();

    o.MyMethod();        // 错误。实例控制者,站在子类(或实现类)角度上也看不到 MyMethod 方法


    class
    MyClass : IMy { protected void MyMethod(){} } 
    //
    正确。继承类(或者说实现类)可见。


    以上模式与问题吗?

    不违背所谓接口 “承诺”的问题吧?因为实例控制者站在接口角度上也看不到protected 方法,也就是说接口没有向实例控制者承诺 MyMethod 方法。对继承类(或实现类)可见,相当于对继承类型承诺有 MyMethod 方法。

    可以这样认为:public 成员相当于对实例控制者承诺,protected成员相当于给继承类型的承诺。

    我绝对现在这个问题已经讨论的跑偏了。问题“接口成员为什么不能有 protected 修饰符”,这个和设计模式无关,非要扯上“设计模式”最多只能说接口加了 protected 修饰机制后,对现有的设计模式有什么影响(好的?或是坏的?),也和你所说的“实作”、“强制”沾不上关系。

    说实话,接口不能有 protected 成员困惑我 N 年,我实在想不通,我认为就是最初 Java 设计接口时遗漏掉了!

    我为什么会有这样的想法呢?因为我曾今 2000 年在网上看过一本电子书,但书名忘了,好像叫什么“XXXX内幕”,讲的就是 Java 为什么单继承,为什么有接口概念。
    下面是这本书对 Java 的负面描述(本人原意描述,不代表我赞成或认同下述言论):

    书本其中部分写到:最初 Java 语言开发时遇到了严重的技术问题就是“多继承”,因为“多继承”是非常复杂的机制,编写支持多继承的编译器技术含金量非常之高,Java 一直解决不掉。后来考虑到 Java 主要针对 PDA 编程(那时候 Java 就是为 PDA 定制的),不像在 PC 上开发应用多继承不是必须,所以就去掉了多继承。去掉多继承以后又发现很多不支持多继承带来负面问题(原文中说了好多问题,记不清了),为了弥补这个缺陷,Java 设计人员胡思乱想的折腾出“接口”这个东西出来,当时连 Java 内部的工程师都认为“接口”就是一个怪胎。

    书本到最后写到:单继承 + 接口  - Java 模式的 OO 歪打正着的成功。Java 最初自己都不看好这种模式,但在后来开发应用中发现“单继承 + 接口”有着独特不可比拟的好处,这种模式开始悄然流行,Java 成功了!

    另,建议:不要用“实作”这个词,很别扭,不符合中国人习惯,还是“实现”比较舒服。

    2012年3月10日 4:49
  • 楼主请稍安勿躁……额……余小章是来自港澳台地区的,可能用语方式略有不同,请谅解。

    至于你说的问题,我之前也说过,确实不错(我个人认为:微软目前只是采取主流的一种做法,当然,任何做法都有优点缺点,你所说的可能会弥补OOP的缺陷,但是也有可能带来其它意想不到的负面作用……)。建议你直接去论坛反馈:http://connect.microsoft.com/,谢谢!!

    一般来说:接口的定义就是“契约”,里边的方法必须是公开的;而抽象类更接近类——这是早先OOP定义的原则,没有理由的。
    当然,你若提出更好的设计原则和理由,建议去微软反映,我们也是没有办法的,呵呵!


       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    • 已标记为答案 大笨虫 2012年3月10日 7:58
    2012年3月10日 5:00
    版主
  • 楼主请稍安勿躁……额……余小章是来自港澳台地区的,可能用语方式略有不同,请谅解。

    至于你说的问题,我之前也说过,确实不错(我个人认为:微软目前只是采取主流的一种做法,当然,任何做法都有优点缺点,你所说的可能会弥补OOP的缺陷,但是也有可能带来其它意想不到的负面作用……)。建议你直接去论坛反馈:http://connect.microsoft.com/,谢谢!!

    一般来说:接口的定义就是“契约”,里边的方法必须是公开的;而抽象类更接近类——这是早先OOP定义的原则,没有理由的。
    当然,你若提出更好的设计原则和理由,建议去微软反映,我们也是没有办法的,呵呵!


       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处


    其实问题的本质就是我所要质疑这个必须要公开的“契约”,不尽人意也不尽合理吗,呵呵。
    • 已标记为答案 大笨虫 2012年3月10日 7:58
    • 取消答案标记 大笨虫 2012年3月14日 3:09
    2012年3月10日 7:48
  • 其实问题你认为没有解决的话,不必要标记答案,呵呵。

    另外,你到我提供的那个站点去访问一下看看那:)提提意见,没有关系的!


       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    2012年3月10日 8:31
    版主
  • dear

    你完全误会我的意思了,

    1.abstract class里的method不一定要宣告成abstract method,这就是我说的不一定要遵守,再method里把abstract 拿掉就好。
    2.对于abstract class而言,他已经实作interface的规范了,若对于继承abstract class而言它还是必须要实作abstract method。
    ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
    这两句跟protected完全无关的,应该是我文章段落没排好,让你误会了,我指的C++里的情况,这是关于C++里的protected,我只把搜寻到的状况分享出来而已,这两句主要想要表达的是目前.NET的语言规范用法,延续上面1,2,我用别的说法,让您参考看看
    1.继承abstract class的class不一定要实现abstract class里的member,因为在abstract class里的member它可以 使用或不使用 abstract关键字。
    2.凡继承interface的class只要写了跟interface相同名称的 member,就算只有壳,里面不写实现过程,在CLR里就算是实现,至少不会出现错误。

    目前就只能尊守C#的规则来走,老实讲,我也有跟你一样的疑问,尤其是疑问4。
    ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
    这句代表我跟你有相同的困惑,因为我也想要写出非公开的规范,让内部的设计师使用


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/

    • 已标记为答案 大笨虫 2012年3月14日 3:09
    2012年3月10日 15:04
  • dear

    你完全误会我的意思了,

    1.abstract class里的method不一定要宣告成abstract method,这就是我说的不一定要遵守,再method里把abstract 拿掉就好。
    2.对于abstract class而言,他已经实作interface的规范了,若对于继承abstract class而言它还是必须要实作abstract method。
    ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
    这两句跟protected完全无关的,应该是我文章段落没排好,让你误会了,我指的C++里的情况,这是关于C++里的protected,我只把搜寻到的状况分享出来而已,这两句主要想要表达的是目前.NET的语言规范用法,延续上面1,2,我用别的说法,让您参考看看
    1.继承abstract class的class不一定要实现abstract class里的member,因为在abstract class里的member它可以 使用或不使用 abstract关键字。
    2.凡继承interface的class只要写了跟interface相同名称的 member,就算只有壳,里面不写实现过程,在CLR里就算是实现,至少不会出现错误。

    目前就只能尊守C#的规则来走,老实讲,我也有跟你一样的疑问,尤其是疑问4。
    ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
    这句代表我跟你有相同的困惑,因为我也想要写出非公开的规范,让内部的设计师使用


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/

     

    PS继承abstract classclass不一定要实现abstract class里的member,因为在abstract class里的member它可以 使用或不使用 abstract关键字


    你上面说的那一条我怎么好像有点看不懂啊?

    子类不实现抽象成员,只可能是以下两种情况吧:
    1
    )抽象类中没有定义抽象成员(仅仅只是 class 修饰了 abstract
    2
    )子类也是抽象类

    写到这里,我才突然明白楼上的意思。
    你的意思应该描述为“抽象类,可以没有抽象成员”,这样让人一下能明白。
    我觉得楼上的朋友,描述风格方法要改进一下,真的很难让人能看完后,立即清晰明白你的意思。

    2012年3月14日 3:08
  • dear

    文字本来就很容易令人误会,一开始我直接就跟你讲结果:"abstract class可以是规范也可以不是规范",不见得会引起你的共鸣,

    所以不管用了再多的文字,若接收的人无法理解,用词再白话也无法达成沟通的目的,不如奈个性子换个方式,直到让对方理解,双方才能达到共试。

    最后,您能明白我的意思那是最好的结果




    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/

    2012年3月14日 8:20
  • dear

    文字本来就很容易令人误会,一开始我直接就跟你讲结果:"abstract class可以是规范也可以不是规范",不见得会引起你的共鸣,

    所以不管用了再多的文字,若接收的人无法理解,用词再白话也无法达成沟通的目的,不如奈个性子换个方式,直到让对方理解,双方才能达到共试。

    最后,您能明白我的意思那是最好的结果




    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/

    呵呵,不过我们讨论的问题已经偏离初衷了啊~~~~
    2012年3月15日 3:05
  • 楼主请稍安勿躁……额……余小章是来自港澳台地区的,可能用语方式略有不同,请谅解。

    至于你说的问题,我之前也说过,确实不错(我个人认为:微软目前只是采取主流的一种做法,当然,任何做法都有优点缺点,你所说的可能会弥补OOP的缺陷,但是也有可能带来其它意想不到的负面作用……)。建议你直接去论坛反馈:http://connect.microsoft.com/,谢谢!!

    一般来说:接口的定义就是“契约”,里边的方法必须是公开的;而抽象类更接近类——这是早先OOP定义的原则,没有理由的。
    当然,你若提出更好的设计原则和理由,建议去微软反映,我们也是没有办法的,呵呵!


       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处


    其实问题的本质就是我所要质疑这个必须要公开的“契约”,不尽人意也不尽合理吗,呵呵。

    这里就存在这样的一个问题,这个“契约”谁定的?定这个“契约”时是不是遗漏了点东西?这个“契约”我们应该不应该质疑?而不应该因为是“契约”就应该推倒一切合理要求~~~~ 如果没有强有力的理由推到 protected 那么这个“契约”就是有残缺的、不完善的部分。

    关于 protected 讨论总结如下:

    1)强制、实作 ---- 不是理由,也不违反(接口有 protected 还是要强制实作的)。

    2)违背承诺 ----- 没有违背,站在实例控制者角度上接口没有承诺 protected 方法(实例控制者看不见 protected 方法),也就是说 protected 就相当于接口专门针对子类做承诺(而不是对实例控制者的承诺),而 public 成员是对子类和实例控制者的共同承诺。

    3)设计模式 ----- 设计模式有很多,通常所说的是基于 OO 的设计模式,OO 是在设计模式之下。上述问题属于 OO 部分,而与设计模式无关(可能会影响到现有设计模式)。

    2012年3月15日 3:39
  • 楼主,我同意你的说法,说实在的,OOP是有问题。不过在目前尚未修正的情况下,我们可以想其它办法弥补,或者绕弯子去完成,不要吊死在一棵树上。:-)

       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    2012年3月15日 6:23
    版主