Java-重写外部方法

Java-重写外部方法,java,overriding,Java,Overriding,我正在尝试为我的应用程序制作一个特殊的附加组件。我需要在不编辑类文件的情况下重写类的某些方法 以下是一个方案: class A { public void method1() { // Do something here } public int method2() { // Do something } } 现在,在我的类B中,我想重写类A中的method1 func,并强制类A使用我的新方法 class B

我正在尝试为我的应用程序制作一个特殊的附加组件。我需要在不编辑类文件的情况下重写类的某些方法

以下是一个方案:

class A
{
    public void method1()
    {
        // Do something here
    }

    public int method2()
    {
        // Do something
    }
}
现在,在我的类B中,我想重写类A中的method1 func,并强制类A使用我的新方法

class B
{
    public void method1()
    {
        Do something
    }
}

我想在不编辑A类的情况下更新我的A类代码。可能吗


谢谢。

通过继承,是的。只需更改类B定义:
类B扩展A

使用
类B扩展A
和要更改的ovverride方法。您必须如何使用类
B
而不是
A
的实例。像

class B extends A
{
    public void method1(){
      Do something
    }
}
A a = new B();
a.method1();

这是没有道理的。重写意味着精确地重新定义从超类继承的方法。以下是一些解决方案:

  • B必须扩展A,然后您可以重写A的一个方法。为其指定与A中相同的签名,请使用@override注释以确保
  • A有一些被注入的依赖项:method1和method2使用一些tierce对象(C)来完成工作,依赖项被注入A。然后B可以使用A和自定义C对象来满足其需要。A的大多数代码不会以这种方式更改

如果使用
构造函数创建对象,则不会。

您可以使用
B
扩展
A
,但必须将对象实例化为
new B()
(即使您可以将它们声明为
A
,如
A obj=new B()
)。

不,在Java等语言中,这是不可能直接实现的<代码>新A
将始终在运行时创建
A
的实例,而不是派生
B
的实例

如果可能(也就是说,如果您控制实例化
A
的所有代码),您可以使用一些引入某种间接寻址的笨拙变通方法。例如,您可以使用一个可配置的工厂来生产
a
s(在封面下按需切换到生产
B
s)——这似乎是Java的方式。(您将需要所有的代码构造
A
s,不是直接使用,而是通过工厂使用。)


如果我没有弄错的话,您正在寻找的特性在Objective C开箱即用中可用,但在Java中不可用。

实现这一点的一种方法是使用某种类型的方法来创建A类型的对象,而不是在代码中直接调用A()构造函数。然后,您的加载项将需要提供并注册它自己的工厂实现,该工厂将创建类B的实例。这仅在加载项在创建任何实例A之前加载并初始化时有效


另一种方法是实现您自己的类加载器,并使用它在加载时修改类A的字节码。您可以搜索用于实现此功能的工具。这只有在您可以控制类A的类加载过程时才可能。不,您不能这样做,在不实际修改类的情况下修改类的行为是不可能的,但是,有一个解决方法:

  • B应该继承自A。这是绝对必要的。A不会改变,但其子类的行为可能会改变

  • 覆盖method1()和method2()

  • 假设您有一个类的对象。如果将其转换为B,则其行为将是新的自定义行为


  • 听起来代理可以解决你的问题。看看

    下面是MyCallback类的示例impl

    class MyCallback implements MethodInterceptor{
           public Object intercept(Object obj,
                                          Method method,
                                          Object[] args,
                                          MethodProxy proxy){
                Object stuffToReturn = null;
                if ("method1".equals(method.getName()) {
                     //Class B's method1 impl 
                } else {
                     //call the original method in class A
                     stuffToReturn  = method.invoke(proxy, args);
                }
    
                return stuffToReturn;   
            }
        }
    

    我不太明白。你是说你现在想要
    A=newa();a、 method1()
    调用
    B.method1
    ?您不能更改类
    a
    中已定义的行为,最好是从类
    a
    扩展并更改类
    B
    中的行为。然后调用类
    B
    对象上的所有方法。在Java中,你不能“替换”原始类,类似于目标C中可能的情况——你需要覆盖并确保其他人使用新类。“我想在不编辑A类的情况下更新我的A类代码”嗯,这不是矛盾吗?@Alvin:在某些语言中,这实际上是可能的。不,
    新的A().method1()
    仍将调用原始的。您将
    B类
    而不是
    A类
    的行为修改为requested@amit如果你读了这篇文章,OP说他不想修改A类。@HunterMcMillen:他想修改
    A
    的行为而不修改它,而不是
    B
    @amit的行为而不编辑源文件,无法更改现有的行为。继承给了他一个解决办法。@HunterMcMillen:那么答案应该是“不,但是…”而不是“是”,这是在改变
    B
    ,而不是
    a
    。这是一种并非总是可行的解决方法
    newa().method1()
    将具有与以前相同的行为。但是-至少这个答案明确提到它只影响
    B
    。谢谢你的回答。有什么方法可以在方法启动时捕获事件吗?我不知道有什么方法,抱歉:(+1.另外,旁注/问题:我不是C#专家,但我知道你可以使用反射在那里动态添加字段-也许也可以[在C#中]这样做?[如果有人知道答案,我会很高兴].但是-在java中,反射无法实现,AFAIK也无法实现。@amit:哇,我不知道这个C#功能!你能分享一些关于它的更多信息吗?(或者这是关于
    ExpandoObject
    ?)@Vlad:正如我所说,我不是C#专家,我只记得一年前读过它[可靠来源]…我不是解决这些问题的地方:)好吧,这不会影响simple
    new A
    实例化的对象的行为。好吧,海报只要求不要修改A类,所以听起来他可以将new A()更改为e.create()?如果海报甚至不能改变
    class MyCallback implements MethodInterceptor{
           public Object intercept(Object obj,
                                          Method method,
                                          Object[] args,
                                          MethodProxy proxy){
                Object stuffToReturn = null;
                if ("method1".equals(method.getName()) {
                     //Class B's method1 impl 
                } else {
                     //call the original method in class A
                     stuffToReturn  = method.invoke(proxy, args);
                }
    
                return stuffToReturn;   
            }
        }