Ответ 1
Создайте третий интерфейс I3 расширяет I1 и I2. Затем классы A и B реализуют I3, а общий метод принимает I3.
Возможно, это единственный способ сделать это.
Предположим, что у меня есть эти интерфейсы:
public interface I1 {
void foo();
}
public interface I2 {
void bar();
}
и классы:
public class A extends AParent implements I1, I2 {
// code for foo and bar methods here
}
public class B extends BParent implements I1, I2 {
// code for foo and bar methods here
}
public class C extends CParent implements I1 {
// code for foo method here
}
Теперь, с generics, у меня может быть такой метод, как:
public <T extends I1 & I2> void method(T param) {
param.foo();
param.bar();
}
и я могу назвать его как A, так и B как параметры, но не с C (он не реализует I2).
Был ли способ достижения этого типа предопределенных типов безопасности (java < 1.5).
Учтите, что A, B и C имеют разные деревья наследования, и на самом деле это не совсем так, как AParent и BParent, которые имеют общий родитель.
Я знаю, что вы могли бы сделать:
public void method(I1 param) {
param.foo();
((I2)param).bar();
}
но затем вы также можете вызвать method(new C())
, который не реализует I2, поэтому вы попадаете в неприятности.
Итак, есть ли другие способы сделать это?
P.S.: Мне действительно не нужно это делать, это в основном из любопытства, о котором я прошу.
Создайте третий интерфейс I3 расширяет I1 и I2. Затем классы A и B реализуют I3, а общий метод принимает I3.
Возможно, это единственный способ сделать это.
Я не думаю, что выше ответы хороши в дизайне. Когда вы создаете интерфейс, вы хотите удостовериться, что объект-вызов имеет ответственность для некоторых действий, определенных в этом интерфейсе. Таким образом, обсуждаются два решения, и я расскажу, почему эти решения не очень хороши в дизайне.
1. сделать один интерфейс расширяет оба двух интерфейса:
public interface IC extends IA,IB {
// empty method here
}
Выше код не имеет смысла. Вы определяете отдельный интерфейс, чтобы комбинировать другие интерфейсы, а внутри нет никаких новых методов. Вы не добавляете значение IC
вместо объединения двух интерфейсов IA
и IB
. И в некоторых ситуациях этот способ сделает ваш код "немного веселым", когда вы не сможете найти подходящее имя для третьего интерфейса. Эта ситуация приведет к некоторому имени интерфейса, например IReadableAndWriteable
или ISomethingAndSomethingAndAnotherThing
2. тип литой внутри метода:
public void methodA(IA object) {
if (object instance of IB) {
((IB)(object)).someMethod()
}
Этот путь тоже бессмыслен. Почему входной параметр IA
, тогда вы должны выполнить какое-либо действие из интерфейса IB
? В соответствии с точкой зрения программиста, нет способа узнать это, кроме как от чтения вашего документа. Это плохо для разработки функции для других людей.
Истинное решение:
В решениях есть еще одна проблема в дизайне: программист force использует один объект, несущий ответственность за два интерфейса. В чем проблема, если программист не хочет этого делать. Они хотят использовать два разных бетонных класса для разных интерфейсов для более простого тестирования, чистого кода? Они не могут.
В вашей сигнатуре метода вы должны сделать два разных параметра:
public void exampleMethod(IA object1, IB object2) {
object1.someMethod()
object2.someMethod()
}
И для вызова метода выше вы вводите один и тот же параметр внутри (если программист использует тот же объект). Они также могут помещать разные объекты.
public void caller() {
IC object3 = new C(); // C is the class implements both IA and IB
exampleMethod(object3, object3);
IA objectA = new A();
IB objectB = new B();
exampleMethod(objectA, objectB);
}
Надеюсь, что эта помощь:)
До версии Java 1.5 в IMO нет решения для достижения такой секретности типа во время компиляции. Но во время исполнения есть душа, используя "экземпляр".
public void method(Object o) {
if (!(o instanceof I1))
throw new RuntimeException("o is not instance of I1");
if (!(o instanceof I2))
throw new RuntimeException("o is not instance of I2");
// go ahead ...
}
sri - лучший ответ, если у вас есть разрешение на изменение подписи A и B. Однако если у вас не было разрешения, вы могли бы сделать:
public void method(I1 param1 , I2 param2) { // unpopular classes that do not implement I3 must use this method
param1.foo();
param2.bar();
}
public void method(I3 param){ // I hope everybody implements I3 when appropriate
param.foo();
param.bar();
}
public void method(A param){// A is a popular class
method(param,param);
}
public void method(B param){// B is a popular class
method(param,param);
}
Конечно, теперь просто используйте generics.