【问题标题】:How can I alter the signature of a member function for a derived class in Java如何更改 Java 中派生类的成员函数的签名
【发布时间】:2010-09-22 01:32:02
【问题描述】:

首先,我扩展了一个现有的类结构,不能改变原来的结构,但要注意:

我想这样做:

class a
{
   int val;

   ... // usual constructor, etc...

   public int displayAlteredValue(int inp)
   {
     return (val*inp);
   }
}

class b extends a
{
   ... // usual constructor, etc...

   public in displayAlteredValue(int inp1, int inp2)
   {
     return (val*inp1*inp2);
   }
}

正如我之前所说,我无法更改 class a,我想保留函数名称 displayAlteredValue,而不是创建一个新函数。 如果可以做到这一点,我只需将a 的一些实例更改为b 的实例。我不想花很多时间来替换对displayAlteredValue 的许多函数调用。 (是的,我确实意识到存在诸如搜索和替换之类的事情,但是由于其他原因,这样做会有问题。

有什么想法吗?

【问题讨论】:

  • 我真的看不出问题;没有什么能阻止你向子类添加另一个方法。您是否试图让现有 displayAlteredValue(int) 方法的调用者神奇地开始使用您的新 displayAlteredValue(int,int) 方法?附加参数的值在哪里?
  • 如果你想让调用者神奇地开始使用新方法,你必须修改所有调用站点以提供第二个参数,我相信你声称你要求避免这种情况。我对这个问题感到困惑。
  • 您似乎正试图阻止用户调用旧方法。做到这一点的唯一方法是通过覆盖它来使该方法在调用它时返回一些无用的东西。

标签: java derived-class


【解决方案1】:

我不清楚问题是什么。您绝对可以创建一个具有相同名称但不同签名的方法的子类 b。

您可能遇到的一个问题是编译器需要知道对象的类型是 b,而不是 a,才能调用只存在于 b 中的方法。

所以这样的代码是行不通的:

// this works because b is a subclass of a
a anObject = new b();

// this will not compile because the declared type of anObject is a
int x = anObject.getValue( 1, 2 );

您必须将变量的声明更改为类型 b,或者在您想要调用 2 参数方法时将其强制转换为 b。

【讨论】:

    【解决方案2】:

    或者,您可以考虑使用组合而不是继承,因为您要扩展的类来自不同的包。

    http://www.artima.com/lejava/articles/designprinciples4.html

    【讨论】:

      【解决方案3】:

      您可以在 B 类中编写如下代码:

      public int displayAlteredValue(int inp) 
      {
          return -1;
      }
      

      并在函数上指出 -1 是错误返回。对于 int 这并没有真正起作用,但如果你返回一个类,如果他们调用方法的单参数版本,你可以返回 null。

      【讨论】:

        【解决方案4】:

        我觉得你的东西很好。

        类 b 的实例可以访问该方法的两个版本。对 1 参数版本的调用将自动路由到 a 类。对 2-arg 版本的调用将转到 b 类。

        虽然 a 类的实例只能访问 1-arg 版本,但我认为没有办法解决。

        【讨论】:

          【解决方案5】:

          您编写的代码按原样编译。您基本上只是重载了该方法。您发布的代码没有完成什么是您想要完成的?您是否试图阻止人们使用单个参数调用 b.displayAlteredValue ?如果是这样,你不能这样做(在编译时),因为它会违反 Liskov 的可替代性原则。

          你可以抛出一个异常,但这不是很好。

          或者,您可以使用组合而不是继承 - 但实际上我们需要更多地了解这种情况才能知道这是否合适。

          【讨论】:

            【解决方案6】:

            您可以在派生类中重载函数。所以你上面指定的应该工作。刚刚写了一个快速测试,它成功了。

            public class DerivedOverload {
            
                /**
                 * @param args
                 */
                public static void main(String[] args) {
                    A classA = new A(); 
            
                    B classB = new B();
            
                    System.out.println("DerivedOverload.main() classA.displayAlteredValue(2) : " + classA.displayAlteredValue(2));
            
                    System.out.println("DerivedOverload.main() classA.displayAlteredValue(2) : " + classB.displayAlteredValue(2,2));
                }
            
            
            
            }
            
            
            class A
            {
               int val = 2;
            
               A(){
            
               }
            
               public int displayAlteredValue(int inp)
               {
                 return (val*inp);
               }
            }
            
            class B extends A
            {
               B(){
            
               }
            
               public int displayAlteredValue(int inp1, int inp2)
               {
                 return (val*inp1*inp2);
               }
            }
            

            系统退出。 DerivedOverload.main() classA.displayAlteredValue(2) : 4 DerivedOverload.main() classA.displayAlteredValue(2) : 8

            【讨论】:

              【解决方案7】:

              如果你把它添加到你的派生类中会怎样

              public int displayAlteredValue(int inp)
              {
                return super.displayAlteredValue(inp);
              }
              

              【讨论】:

              • 何必呢?通过派生该类,对 displayAlteredValue 的任何调用都已完成此操作。
              • 不,他们没有。查找方法重载和方法隐藏的区别。
              • 我说的是使用此签名的调用,而不是对重载方法的调用。这个答案是建议覆盖 A 的定义,而不是重载,它只是调用 A 的定义,没有意义。
              猜你喜欢
              • 2021-03-24
              • 2011-09-24
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-07-05
              • 2021-03-25
              • 1970-01-01
              • 2013-08-22
              相关资源
              最近更新 更多