Java泛型,返回类型以仅访问抽象类型的受保护方法

huangapple go评论80阅读模式
英文:

Java Generics, return type to access only protected methods of the abstract type

问题

我在我的应用程序中有以下设置
```java
// 包 1
public class class1 extends AbstractClass2<class1>{

  public void someMethod(){
    // 我想要的是当我调用方法 “with” 时,我应该只能链接在 AbstractClass3 中定义的方法,而不是在其子类中定义的方法。
    with(10).someOtherMethod() // 这应该是可能的(在当前设置下是可能的)
    with(10).someMethod() // 这不应该是可能的(在当前设置下是可能的)
  }

}

// 包 2
public abstract class AbstractClass2<T> extends AbstractClass3<T>{
  protected void someMethod(){
  }
}

public abstract class AbstractClass3<T>{
  
  protected T with(int value){
    setValue(value);
    return (T) this;
  }

  protected void someOtherMethod(){
  }

}

基本上我想要实现方法链式调用,但限制在基类 "AbstractClass3" 中定义的方法。我应该如何实现这一点?

英文:

I have the following settings in my application

//Package 1
public class class1 extends AbstractClass2&lt;class1&gt;{
  
  public void someMethod(){
    // What i want here is when i call the method &quot;with&quot;, I should be able to chain only 
    // the methods defined in AbstractClass3 and not the methods defined in its sub classes.
    with(10).someOtherMethod() // this should be possible (it is possible with the current setup)
    with(10).someMethod() // this should not be possible (it is possible with the current setup)
  }

}

//Package 2
public abstract class AbstractClass2&lt;T&gt; extends AbstractClass3&lt;T&gt;{
  protected void someMethod(){
  }
}

public abstract class AbstractClass3&lt;T&gt;{
  
  protected T with(int value){
    setValue(value);
    return (T) this;
  }

  protected void someOtherMethod(){
  }

}

Basically what i am trying to achieve method chaining, but limit it to the methods defined in the base class "AbstractClass3". How should i achieve this?

答案1

得分: 0

问题出在with(int value)someOtherMethod()方法中。并且在AbstractClass3中不需要使用泛型(至少在您提供的示例中是这样的)。

您的“with”方法应为protected AbstractClass3 with(int value)。请注意,该方法现在返回一个AbstractClass3,这意味着只有在该类中定义的方法才可用(除非您将其转换为子类)。

最后,在someOtherMethod()的方法可见性中有一个巧妙的技巧,它应为public。如果您在不同的包中,只能通过this.引用调用受保护的方法(当然是通过继承)。

我认为在代码中通过注释更好地解释了这一点:

public abstract class AbstractClass3 {

    protected AbstractClass3 with(int value) {
        // 进行一些操作。
        return this;
    }

    // 如果“someOtherMethod()”是受保护的,您只能在不同包中使用“this.”引用从子类调用它。
    // 所以,我们将其设为public。
    public void someOtherMethod() {
    }

}

public abstract class AbstractClass2<T> extends AbstractClass3 {
    protected void someMethod() {
    }
}

public class Class1 extends AbstractClass2<ANY_CLASS_HERE> {

    public void someMethod() {
        // 如果someOtherMethod()是受保护的,这将不起作用,因为您没有通过“this.”引用来调用它。
        // 只有在不同包中,您才能通过“this.”引用调用受保护的方法。
        // 由于您正在从由“with(10)”返回的另一个实例中调用someOtherMethod(),这意味着您是在“外部”调用它;
        // 而“this.”引用位于由“with(10)”返回的实例的“内部”。为了使其工作,someOtherMethod()必须是public的(或者在同一个包中)。
        // 请记住:在不同的包中调用受保护方法需要使用“this.”引用。
        with(10).someOtherMethod();

        // 如果someOtherMethod()是受保护的,这将起作用,因为您是通过“this.”引用调用它的。
        // 这是对父类的直接调用。
        this.someOtherMethod(); // 注意“this.”引用。

        // 错误,因为someMethod()在AbstractClass3和“with(10)”中都不存在。
        // 返回一个AbstractClass3实例。
        with(10).someMethod();
    }

}

我从AbstractClass3中删除了泛型,但您随时可以重新添加。这里重要的是您理解您的“with”方法应返回AbstractClass3,并且如果在不同的包中,受保护的方法只能通过this.引用来调用。

英文:

The problem is in with(int value) and someOtherMethod(). And you also do not need generics in AbstractClass3 (at least in the example you provided).

Your "with" method should be protected AbstractClass3 with(int value). Note that the method now returns a AbstractClass3, which means that only methods defined in this class will be available (unless you cast it to a sub-class).

Finally, there is a catchy trick in the method visibility of someOtherMethod() which should be public. If you are in a different package, you can only call protected methods through this. reference (by inheritance, of course).

I think it's better explained in the code with comments:

public abstract class AbstractClass3 {

	protected AbstractClass3 with(int value) {
		// Do stuff.
		return this;
	}

	// If &quot;someOtherMethod()&quot; is protected, you will only be able to call
	// it from sub-classes using &quot;this.&quot; reference if you are in a different package.
	// So, we make it public.
	public void someOtherMethod() {
	}

}

public abstract class AbstractClass2&lt;T&gt; extends AbstractClass3 {
	protected void someMethod() {
	}
}

public class Class1 extends AbstractClass2&lt;ANY_CLASS_HERE&gt; {

	public void someMethod() {
		// If someOtherMethod() is protected, this will NOT work because you are not calling it
		// through &quot;this.&quot; reference. YOU CAN ONLY CALL PROTECTED METHODS THROUGH &quot;this.&quot; reference
		// IF YOU ARE IN A DIFFERENT PACKAGE. As you are calling someOtherMethod() from another 
		// instance returned by &quot;with(10)&quot;, that means that you are calling it &quot;outside&quot;; 
		// the &quot;this.&quot; reference is &quot;inside&quot; the instance returned by &quot;with(10)&quot;. In order for 
		// it to work, someOtherMethod() must be public (or be in the same package).
		// Remember: You need &quot;this.&quot; reference to call protected methods in different packages.
		with(10).someOtherMethod();

		// If someOtherMethod() is protected, this works because you are calling
		// it through &quot;this.&quot; reference. It&#39;s a straight call to the parent.
  		this.someOtherMethod(); // Note the &quot;this.&quot; reference.

		// ERROR because someMethod() does not exists in AbstractClass3 and &quot;with(10)&quot;.
		// returns an AbstractClass3 instance.
  		with(10).someMethod();
	}

}

I took the generics out of AbstractClass3 but you can get it back anytime. The important thing here is you understand that your "with" method should return AbstractClass3 and that protected methods can only be called through this. reference if you are in a different package.

huangapple
  • 本文由 发表于 2020年4月7日 03:44:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/61067742.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定