【问题标题】:Language Agnostic Basic Programming Question与语言无关的基本编程问题
【发布时间】:2010-04-10 13:09:43
【问题描述】:

从编程的角度来看,这是一个非常基本的问题,但由于我处于学习阶段,我认为我最好问这个问题,而不是对该主题有误解或狭隘的知识。

如果我搞砸了,请原谅我。

问题

假设我有class A,B,C and D 现在class A 有一些我需要在class B,C and D 中拥有的代码,所以我在class B, class C, and class D 中扩展class A

现在我如何在其他类中访问class A 的函数,我是否需要创建class A 的对象,而不是访问class A 的函数或者在我以外的其他类中扩展A可以使用此参数在内部调用该函数。

如果可能的话,如果有人能用解释逻辑如何流动的代码示例来解释这个概念,我将不胜感激。

注意

Java、PHP 和 .Net 中的示例将不胜感激。

【问题讨论】:

    标签: language-agnostic oop programming-languages


    【解决方案1】:

    让我们忘记 C 和 D,因为它们与 B 相同。如果 B 类扩展了 A 类,那么 B 类型的对象也是 A 类型的对象。每当您创建 B 类型的对象时,您也在创建一个对象类型 A。它应该可以访问 A 中的所有方法和数据(如果您的语言支持访问修饰符,则标记为私有的除外)并且可以直接引用它们。如果 B 覆盖了 A 的某些功能,那么通常该语言会提供调用基类实现的工具(base.Foo() 或类似的)。

    继承示例:C#

    public class A
    {
         public void Foo() { } 
         public virtual void Baz() { }
    }
    
    public class B : A  // B extends A
    {
          public void Bar()
          {
              this.Foo();  // Foo comes from A
          }
    
          public override void Baz() // a new Baz
          {
              base.Baz();  // A's Baz
              this.Bar();  // more stuff
          }
    }
    

    另一方面,如果您使用组合而不是继承,并且 B 包含 A 的实例作为类变量,那么您需要创建 A 的对象并引用它的 ( public) 功能通过该实例。

    组合示例:C#

     public class B // use A from above
     {
         private A MyA { get; set; }
    
         public B()
         {
             this.MyA = new A();
         }
    
         public void Bar()
         {
             this.MyA.Foo();  // call MyA's Foo()
         }
     }
    

    【讨论】:

    • 您能否详细说明组合部分而不是继承,因为它不是很清楚?
    • @Rachel:通过组合,你实质上是将 B.Bar() 的调用转发给 A.Foo()。这通常在 A 和 B 不形成“is-a”关系时使用。例子:Ford is-a Car 所以 Ford 继承 Car 来共享实现;但 Car 不是 Steering 虽然 Car 具有使其可转向的属性,但组合比继承更能反映这一事实。
    • @Rachel -- 我添加了一个例子。这有帮助吗?
    • 我没有得到两个反对票——有人愿意纠正我在这里弄错的地方吗?
    • 我现在肯定明白了。
    【解决方案2】:

    根据访问级别(在 .NET 中将受到保护或公开),您可以使用以下内容:

    base.method(argumentlist);
    

    我的示例中的 base 关键字特定于 C#

    不需要A类的实例,因为你已经有一个A类继承的实例

    【讨论】:

      【解决方案3】:

      基本上你需要一个对父类的引用。

      在 PHP 中:

      parent::example();
      

      发件人:http://www.php.net/manual/en/keyword.parent.php

      <?php
      class A {
          function example() {
              echo "I am A::example() and provide basic functionality.<br />\n";
          }
      }
      
      class B extends A {
          function example() {
              echo "I am B::example() and provide additional functionality.<br />\n";
              parent::example();
          }
      }
      
      $b = new B;
      
      // This will call B::example(), which will in turn call A::example().
      $b->example();
      ?>
      

      【讨论】:

      • 你能详细解释一下吗?
      • 添加来自 php.net 的示例有意义吗?
      • 现在让我们说如果我没有在class B 中创建函数而不是我如何直接调用class A 中的函数,我是否需要在class B 之前创建class A 的实例访问 class A 函数,即使 class B 正在扩展 class A
      • 您不必创建class A 的实例来访问这些方法。
      • 所以我可以直接使用$this-&gt;Class A Method 来访问A类函数?
      【解决方案4】:

      我发现驯服继承复杂性的最佳方法是确保我只让B 继承自A,当它确实是超类的特化时。那时,我可以从B 内部调用A 的方法,就好像它们是B 自己的方法一样,如果B 覆盖了它们,那么我只能假设这一定是为了一个很好的理由。

      当然,B 的方法实现在同一个对象上调用A 的实现通常很有用,这通常是因为子类围绕超类的基本定义包装了额外的行为。您执行此操作的方式因语言而异;例如,在 Java 中你可以这样做:

      super.methodName(arg1, ...);
      

      【讨论】:

        【解决方案5】:

        这是一个简单的 Java 示例:

        public class Aclass
        {
            public static void list_examples()
            {
                return("A + B = C");
            }
        }
        public class Bclass extends Aclass
        {
            public static void main(String [] args)
            {
                System.out.println("Example of inheritance "+list_examples);
            }
        }
        

        请注意,访问父类的方法不应该改变。因为您正在扩展,所以您不必说 parent:: 或任何内容除非您覆盖父方法/函数

        【讨论】:

          【解决方案6】:

          在我看来,扩展您的课程可能不是您的最佳选择。类“B”、“C”和“D”只应扩展类“A”,如果它们确实是该类的扩展,而不仅仅是访问某些方法。例如,“Huffy”不应仅仅因为“Huffy”是一个品牌名称而扩展“BrandNames”,而您想要访问“BrandNames”的方法之一。 “Huffy”应该扩展“Bicycle”并实现一个接口,以便可以使用“BrandNames”的方法。这里的另一个好处是(在 Java 中)可以使用多个接口,但一个类只能扩展一次。如果在您的示例类“B”中需要访问可以工作的“A”类中的方法,但如果“C”类需要访问“A”类和“B”类中的方法,那么您将拥有使用类“'C”中的接口。

          【讨论】:

            猜你喜欢
            • 2013-06-19
            • 1970-01-01
            • 1970-01-01
            • 2011-08-04
            • 1970-01-01
            • 1970-01-01
            • 2011-08-20
            • 1970-01-01
            • 2021-12-13
            相关资源
            最近更新 更多