【问题标题】:Multiple inheritance without multiple inheritance and without code duplication多重继承,无多重继承,无代码重复
【发布时间】:2012-06-02 04:48:57
【问题描述】:

我有一个关于如何在不允许多重继承的语言中处理以下场景的理论问题。

假设我有一个基类 Foo,我希望从中创建三个子类:

  • Bar继承Foo并实现功能“A”
  • Baz继承Foo并实现功能“B”
  • Qux继承Foo并实现功能“A”和“B”

想象一下,实现功能“A”和“B”的代码总是相同的。有没有办法只为“A”和“B”编写一次代码,然后让适当的类应用(或“继承”)它?

【问题讨论】:

  • 任何特定的语言?爪哇? C#?还有什么?
  • 为什么你不在你的 FOO 类中实现相同的功能,而只是将 A/B 标记为虚拟/可覆盖?
  • @Tudor 正在考虑使用 C#,但任何不允许多重继承的 OOP 语言都可以。
  • @YavgenyP - 假设 FOO 和后代用于连接到服务器,功能 A 提供了一种添加到标准 FOO 连接机制并允许经过身份验证的请求的方法。覆盖连接方法可以解决问题,但我必须在 BAR 和 QUX 中都进行覆盖。如果代码相同,我最终会得到两个副本。希望有一个我不知道的更优雅的解决方案。
  • @Mr_Creosote:我放 C# 和 Java 标签只是为了获得浏览量,因为你原来的两个标签不那么受欢迎。

标签: c# java oop inheritance


【解决方案1】:

有几种方法可以做这样的事情。更具体地说,如果我们暂时放弃继承方面,有一些方法可以将相同的功能单元引入不同的类,而只需编写一次该单元。

好的,我喜欢 AOP 框架,它们适用于多种语言(C# 和 Java 有好几种)。 AOP 框架基本上允许您将自包含功能添加到整个继承结构中的不同类中。

对于 C#,您有 PostSharp,对于 Java,您有 AspectJ,等等。

许多 AOP 框架允许在不使用继承的情况下“劫持”或“覆盖”方法调用。

【讨论】:

    【解决方案2】:

    对此更通用的术语是Mixin。一些语言提供开箱即用的支持,例如 Scala 和 D。不过,有多种方法可以在其他语言中实现相同的结果。

    在 C# 中创建伪混合的一种方法是使用空接口并为方法提供扩展方法。

    interface A { }
    static class AMixin {
        public static void aFunc(this A inst) {
            ... //implementation to work for all A.
        }
    }
    
    interface B { }
    static class BMixin {
        public static void bFunc(this B inst) {
            ...
        }
    }
    
    class Qux : Foo, A, B {
        ...
    }
    

    【讨论】:

      【解决方案3】:

      嗯,我能看到你在 C#/Java 中实现这一点的唯一方法是组合。考虑一下:

      class Foo {
      
      }
      
      interface A {
          public void a();
      }
      
      interface B {
          public void b();
      }
      
      class ImplA implements A {
          @Override
          public void a() {
              System.out.println("a");
          }
      }
      
      class ImplB implements B {
          @Override
          public void b() {
              System.out.println("b");
          }
      }
      
      class Bar extends Foo {
          A a = new ImplA();
      
          public void a() {
              a.a();
          }
      }
      
      class Baz extends Foo {
          B b = new ImplB();
      
          public void b() {
              b.b();
          }       
      }
      
      class Qux extends Foo {
      
          A a = new ImplA();
          B b = new ImplB();
      
          public void b() {
              b.b();
          }
      
          public void a() {
              a.a();          
          }       
      }
      

      现在Qux 既具有Foo 通过正常继承的功能,又具有AB 通过组合的实现。

      【讨论】:

        【解决方案4】:

        这在提供特征的语言中是可以实现的(这里:):

        class Foo {
            def fooM() {}
        }
        
        trait A {
            def aFunc() {}
        }
        
        trait B {
            def bFunc() {}
        }
        
        class Bar extends Foo with A {}
        
        class Baz extends Foo with B {}
        
        class Qux extends Foo with A with B {}
        

        因为 Scala 在 Java 之上运行(既没有多重继承也没有特征),所以它被翻译成类似这样的东西(简化)——这可能暗示了如何在 Java/C# 中手动实现它:

        class Foo {
        }
        
        interface A {
            void aFunc();
        }
        
        interface B {
            void bFunc();
        }
        
        class Bar extends Foo implements A {
        
            public void aFunc() {
                $A.aFunc();
            }
        }
        
        class Baz extends Foo implements B {
        
            public void bFunc() {
                $B.bFunc();
            }
        }
        
        class Qux extends Foo implements A, B {
        
            public void aFunc() {
                $A.aFunc();
            }
        
            public void bFunc() {
                $B.bFunc();
            }
        }
        
        class $A {
        
            public static void aFunc() {}
        }
        
        class $B {
        
            public static void bFunc() {}
        }
        

        【讨论】:

          猜你喜欢
          • 2013-07-24
          • 1970-01-01
          • 2015-04-28
          • 1970-01-01
          • 1970-01-01
          • 2023-03-04
          • 2010-09-27
          • 2012-03-07
          相关资源
          最近更新 更多