Is the following possible somehow?
interface Foo<T> {
public void bar(T object);
}
...
public void callBar(Foo<?> foo) {
foo.bar("Hello world!");
}
Clearly, this is not type-safe as it is assuming that Foo<?> in this case actually is a Foo<String>.
But rather than the usual "unchecked" warning, this actually gives me the following error: The method bar(capture#1-of ?) in the type Foo is not applicable for the arguments (String)
Usually there's some casting I can do to turn this exception into the warning I want, but somehow I can't find one right now...
Any thoughts (other than "don't do this!", please)?
EDIT:
It seems like everyone does want to discuss the "don't do this", so let me explain the entire problem I'm trying to solve as elegantly as possible and then maybe someone has a cleaner way to do this...
I'm trying to write a flexible eventbus system, where I don't need to declare a billion interface types for each event.
I want to have a class EventBus that looks like this:
public class EventBus<GroupType, EventType> {
...
public void addHandler(EventHandler<GroupType, EventType, ?> handler, GroupType group, EventType... events) {
// ^ this is the <?> !!!
// add handler to list of handlers for group and requested event types
}
public <Source> void fireEvent(GroupType group, EventType event, Source source) {
// call all handlers registered for group and event type
}
}
where the interface EventHandler looks like this:
public interface EventHandler<GroupType, EventType, Source> {
public void onEvent(GroupType group, EventType event, Source source);
}
That way, I can simply write my event handlers to look like this:
public class Handler implements EventHandler<Groups, Events, TextBox> {
public void onEvent(Groups group, Events event, TextBox source) {
// Do something with source immediately
}
}
where Groups and Events are Enums that describe the possible event types.
Then I register them with
addHandler(myHandler, Groups.EDIT_BOXES, Events.VALUE_CHANGED, Events.CLEARED, ...);
And I can call them with
fireEvent(Groups.EDIT_BOXES, Events.VALUE_CHANGED, myEditField);
In my code, I know that in the group EDIT_BOXES all sources are of type TextBox and I don't want to type-cast my life away in every handler I write. That's why I would like to be able to implement the specific interface in the handler, but call it with an unsafe typecast from the EventBus (which I write once and hide forever) rather than having to write all my handlers like this:
public class Handler implements EventHandler<Groups, Events> {
public void onEvent(Groups group, Events event, Object source) {
TextBox usableSource = (TextBox) source;
// Do something with usableSource
}
}
And if the cast is wrong, the program will and should crash and burn either way. Even if I put an "instanceof" check in the handler, I will need to somehow throw that as an error. I can do that elegantly, but it doesn't really matter, since any error in this scenario is a bug in the code that needs to be fixed and not some runtime user-error, which I should gracefully inform the user of.
Now, I've seen other libraries implement a completely type-safe event system, but often this involves having to declare interfaces for every possible type of event and every possible type of event handler and sometimes even for functions on the eventbus itself, which, if you ask me, is WAY more pain than it's worth.
If any of you have a clean way to do what I'm trying to achieve, I'd be stoked. But I'm not sure it's doable any other way.
You propose that this is a solution:
public void callBar(Foo<?> foo) {
((Foo<String>) foo).bar("Hello world!");
}
I claim that if this does work that there is something wrong with your API's typing.
One possibility is that all the places where callBar is going to be called, the foo will actually be a Foo<String>. But if that is the case, then the (generic) method signature is incorrect. You should declare it as:
public void callBar(Foo<String> foo) {
foo.bar("Hello world!");
}
Another possibility is that the bar method will actually work just fine when called with an argument that doesn't match the generic type; e.g.
Foo<Integer> f = ...
f.bar("Hello world!");
doesn't cause any runtime breakages due to "Hello world!" having the wrong time. In that case you have probably declared the method signature in the interface incorrectly. It should be:
public void bar(Object object);
A third possibility is that your code works for a particular implementation of the Foo.bar method, and that you are only going to use it with those implementations. But if that is the case, your code should reflect this:
public void callBar(Foo<?> foo) {
if (foo instanceof SomeFooImpl) {
foo.realBar("Hello world!");
} else {
throw InvalidArgument("barring the wrong kind of foo");
}
}
and
public class SomeFooImpl<T> implements Foo<T> {
...
public void bar(T object) {
realBar(object);
}
publiC void realBar(Object object) {
System.out.print("Breaker breaker - come in '" + object + "'"));
}
}
(Note we can't overload bar and realBar; i.e. give them the same name. The methods need to have different erased signatures ...)
But the bottom line is that what you are proposing as the correct solution is liable to result in the foo method being called with an actual argument that doesn't match the base type. That is WRONG, at least from perspective of the type signatures as you have declared them.
UPDATE in response to your comment.
I think that the best solution is to change this:
public interface EventHandler<GroupType, EventType, Source> {
public void onEvent(GroupType group, EventType event, Source source);
}
to
public interface EventHandler<GroupType, EventType> {
public void onEvent(GroupType group, EventType event, Object source);
}
This means that a specific handler will need to type-cast the source object to the type that it is expecting. But this is pretty much mandated your EventBus API ... which seems to be saying that the handler registration and dispatching is agnostic of the source type of the handler objects. It is probably good from a functional perspective too, because it allows a single handler to handle events from multiple source types.
(Comment: your API design looks like you might be focussing too much on elegant use of generics ... at the expense of supporting the functionality that an event bus needs to provide. My conception of an event bus is that it should avoid static dependencies between the suppliers and consumers of events. This means that it needs to be able to dynamically "deal with" type mismatches between the the producers and consumers. But your use of generics seems to be (re-)introducing static type dependencies ... )
If you have a generic interface, don't make the method call it with a specific type. Or don't use a specific type and stay generic
interface Foo<T> {
public void bar(T object);
}
class SomeGenericClass {
public <T> void callGenericBar(Foo<T> foo, T param) {
foo.bar(param);
}
public void callStringBar(Foo<String> foo) {
foo.bar("Hello");
}
}
If you do it like
public void callBar(Foo<?> foo) {
((Foo<String>) foo).bar("Hello world!");
}
The following code will compile fine:
interface Foo<T> {
public void bar(T object);
}
class StringFoo implements Foo<String> {
public void bar(String object) {
System.out.println(object);
}
}
class IntFoo implements Foo<Integer> {
public void bar(Integer object) {
System.out.println(object);
}
}
class TestClass {
public static void callBar(Foo<?> foo) {
((Foo<String>) foo).bar("Hello world!");
}
public static void main(String[] args) {
StringFoo foo1 = new StringFoo();
IntFoo foo2 = new IntFoo();
callBar(foo1);
callBar(foo2);
}
}
But: once you run it you get
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
It requires that foo is a Foo<String>. Use
public static void callBar(Foo<String> foo) {
foo.bar("Hello world!");
}
And if you have multiple types of Foo use method overloading.
Never mind... Just figured it out:
public void callBar(Foo<?> foo) {
((Foo<String>) foo).bar("Hello world!");
}
Related
While trying to program to interfaces, I regularly find myself in the following situation:
I have several very similar classes representing containers or algorithms for different types.
I would like to define a common interface for these classes.
Consider, e.g., a string container.
Such a container will likely have string processing methods.
Since those methods are easily represented using generic interfaces, I am ignoring them.
Here, I want to focus on methods that can be used to process or provide references to other string containers:
public class StringContainer {
StringContainer produce() {
return new StringContainer();
}
void consume(StringContainer stringContainer) {
}
}
This class can be used just fine in code like:
public class Main {
public static void main(String[] args) {
StringContainer stringContainer = new StringContainer();
stringContainer.produce();
stringContainer.consume(stringContainer);
}
}
The problem is: I'm using a concrete class and not an interface to refer to the string container.
What if I want to introduce a double container or a list container later and want to leave the rest of the code as is?
Maybe generics could form a solution to this problem?
Here is my try.
I first define a generic container class:
interface Container<T> {
Container<T> produce();
void consume(Container<T> container);
}
I then create type-specific implementations of the form:
public class StringContainer implements Container<String> {
#Override
public Container<String> produce() {
return new StringContainer();
}
#Override
public void consume(Container<String> container) {
}
public void consume(StringContainer container) {
}
}
The above classes can be used as follows:
public class Main {
public static void main(String[] args) {
Container<String> stringContainer = new StringContainer();
stringContainer.produce();
stringContainer.consume(stringContainer);
}
}
However, the above approach has several drawbacks:
The consume(Container<String> container) method accepts other types than StringContainer.
In consume(Container<String> container), the parametrized type Container<String> has to be used when processing container. I can't assign it to StringContainer variables (without type checks or casts).
The alternative consume(StringContainer container) method is defined for StringContainer objects, but can't be called from a Container<String> reference.
Finally, to me, the line Container<String> stringContainer = new StringContainer(); has an awkward-looking notation that suggests a diamond operator is missing in new StringContainer().
What is the idiomatic way to define a general interface for several type-specific classes, which doesn't have (all) the above drawbacks?
Should I ignore point 4 and address points 1 and 2 by adding type checks/casts, throwing an UnsupportedOperationException or IllegalArgumentException in case passed objects aren't StringContainers?
Or is there another way to use generics? Can type bounds help me, for example?
Or should I look for a solution outside of generics?
Update:
Based on the answers given so far, I have come to realize that I had conflicting goals:
On the one hand, I wanted to restrict the types accepted by container methods (as described by points 1 and 2).
On the other hand, I wanted to address and pass container types using an interface reference (as hinted at by point 3 and my implicit desire to keep the second main method as is).
I now see that these goals cannot both be reached statically.
Since I don't want to rephrase my question in retrospect, I'll forget about my second (rather implicit) goal and mark the first-posted solution that addressed points 1 and 2 as the answer.
Is this what you're looking for? It's called a recursive type bound.
interface Container<T extends Container<T>> {
T produce();
void consume(T container);
}
class StringContainer implements Container<StringContainer> {
#Override
public StringContainer produce() {
return new StringContainer();
}
#Override
public void consume(StringContainer container) {
}
}
It seems that you have two APIs, and you should treat them separately with separate interfaces. Yes, you can merge them into the same interface with distinct method names.
I think you should have two interfaces for your "containers" and for your "containers of containers". Here's what I'd make it:
interface Container<T> {
T produce();
void consume(T container);
}
interface MetaContainer<T, R extends Container<T>> {
R produceContainer();
void consumeContainer(R container);
}
class StringContainer implements Container<String>, MetaContainer<String, StringContainer> {
#Override
public String produce() {
return "";
}
#Override
public void consume(String container) {
}
#Override
public StringContainer produceContainer() {
return this;
}
#Override
public void consumeContainer(StringContainer container) {
}
}
I implemented both interfaces using the same class to emulate your StringContainer class.
I wanted to know what are the advantages / disadvantages of using each of the following ways to differentiate between sub-classes of the main parent class and handle them differently. I know this is pretty basic, but i couldnt find a full comparison between these ways anywhere.
For example:
- I have a Payment super abstract class and two extending classes OneTimePayment and Subscription
- I have a method switchPaymentState that should handle each one of these types differently
Option 1: Using instanceof
public void switchPaymentState(Payment payment) {
if(payment instanceof OneTimePayment) {
//do something
} else if(payment instanceof Subscription) {
//do something else
}
}
Option 2: Using enum type argument (or other...)
public enum PaymentType {
ONE_TIME_PAYMENT,
SUBSCRIPTION;
}
public abstract Payment(PaymentType type) {
this.type = type;
}
public OneTimePayment() {
super(ONE_TIME_PAYMENT);
}
public Subscription() {
super(SUBSCRIPTION);
}
and then:
public void switchPaymentState(Payment payment) {
switch(payment.type) {
case ONE_TIME_PAYMENT:
//do something
break;
case SUBSCRIPTION:
//do something
break;
}
}
Option 3: Using overload methods
public void switchPaymentState(OneTimePayment payment){
//do something
}
public void switchPaymentState(Subscription payment){
//do something
}
So, which is the best way to go (or a complete other way?) and why?
EDIT:
The operations i need to do based on the class type are NOT operations on the class itself, i need to take some data form the payment and send it via other services, so solutions like implementing this functionality inside the classes and calling it regardless of the type, will unfortunately not help in this case. Thanks!
The most modular way would be to use overriding.
You'll have a single switchPaymentState method which accepts the base type - Payment - and calls a method in the Payment class to do the handling. That method can be overridden in each sub-class of Payment.
public void switchPaymentState(Payment payment)
{
payment.handlePayment();
}
Your switchPaymentState method doesn't have to know which sub-classes of Payment exist, and it doesn't have to change if you add new sub-classes tomorrow.
Your option 3 will in many cases not work, because overloading is resolved atcompile-time rather than at run-time. If the type of your references is Payment, it is not possible to use overloading.
In terms of object-oriented design, using overridden methods is the "cleanest" method. However, it has the disadvantage that similar functionality is spead over multiple classes, whereas in the switch and instanceof solutions everything is together.
An alternative that offers the best of both worlds is the so-called Visitor Pattern. You create an interface PaymentVisitor with for each class you want a handle a method, as follows:
interface PaymentVisitor {
void visitOneTimePayment(OneTimePayment payment);
void visitSubscription(Subscription payment);
}
Then in you abstract superclass you add a method visit:
abstract class Payment {
...
abstract void callVisitor(PaymentVisitor visitor);
}
Which you implement in all you subclasses as follows:
class OneTimePayment {
...
#Override void callVisitor(PaymentVisitor visitor) {
visitor.handleOneTimePayment(this);
}
}
class Subscription {
...
#Override void callVisitor(PaymentVisitor visitor) {
visitor.handleSubscription(this);
}
}
Now, in all cases where you would otherwise write something like (in pseudo-Java):
switch (type of x) {
case OneTimePayment:
// Code
break;
case Subscription:
// Code
break;
}
You can now write, cleanly and type-safe:
x.callVisitor(new PaymentVisitor() {
#Override void handleOneTimePayment(OneTimePayment payment) {
// Code
}
#Override void handleSubscription(Subscription payment) {
// Code
}
});
Note also that the visitor is implemented in an inner class, so you still have access to all (effectively) final variables defined in the method body.
I think the switch is a bit of an anti-pattern regardless of how you do it. The more standard OO way would be to implement the same method or methods in both of the subclasses, and let each class manage things as appropriate. In other words
abstract class Payment {
abstract void processPayment(BigDecimal amount);
abstract void processRefund...
}
class OneTimePayment extends Payment {
void processPayment(BigDecimal amount){... }
void processRefund...
}
etc.
Also, unless you're reusing a considerable amount of code in the super class, consider an interface-based implementation instead of subclassing.
This question already has answers here:
How to make a Java class that implements one interface with two generic types?
(9 answers)
Closed 8 years ago.
I have the following interface, which I want to implement multiple times in my classes:
public interface EventListener<T extends Event>
{
public void onEvent(T event);
}
Now, I want to be able to implement this interface in the following way:
class Foo implements EventListener<LoginEvent>, EventListener<LogoutEvent>
{
#Override
public void onEvent(LoginEvent event)
{
}
#Override
public void onEvent(LogoutEvent event)
{
}
}
However, this gives me the error: Duplicate class com.foo.EventListener on the line:
class Foo implements EventListener<LoginEvent>, EventListener<LogoutEvent>
Is it possible to implement the interface twice with different generics? If not, what's the next closest thing I can do to achieve what I'm trying to do here?
Is it possible to implement the interface twice with different generics
Unfortunately no. The reason you can't implement the same interface twice is because of type erasure. The compiler will handle type parameters, and a runtime EventListener<X> is just a EventListener
If not, what's the next closest thing I can do to achieve what I'm trying to do here?
Type erasure can work in our favor. Once you know that EventListener<X> and EventListener<Y> are just raw EventListener at run-time, it is easier than you think to write an EventListener that can deal with different kinds of Events. Bellow is a solution that passes the IS-A test for EventListener and correctly handles both Login and Logout events by means of simple delegation:
#SuppressWarnings("rawtypes")
public class Foo implements EventListener {
// Map delegation, but could be anything really
private final Map<Class<? extends Event>, EventListener> listeners;
// Concrete Listener for Login - could be anonymous
private class LoginListener implements EventListener<LoginEvent> {
public void onEvent(LoginEvent event) {
System.out.println("Login");
}
}
// Concrete Listener for Logout - could be anonymous
private class LogoutListener implements EventListener<LogoutEvent> {
public void onEvent(LogoutEvent event) {
System.out.println("Logout");
}
}
public Foo() {
#SuppressWarnings("rawtypes")
Map<Class<? extends Event>, EventListener> temp = new HashMap<>();
// LoginEvents will be routed to LoginListener
temp.put(LoginEvent.class, new LoginListener());
// LogoutEvents will be routed to LoginListener
temp.put(LogoutEvent.class, new LogoutListener());
listeners = Collections.unmodifiableMap(temp);
}
#SuppressWarnings("unchecked")
#Override
public void onEvent(Event event) {
// Maps make it easy to delegate, but again, this could be anything
if (listeners.containsKey(event.getClass())) {
listeners.get(event.getClass()).onEvent(event);
} else {
/* Screams if a unsupported event gets passed
* Comment this line if you want to ignore
* unsupported events
*/
throw new IllegalArgumentException("Event not supported");
}
}
public static void main(String[] args) {
Foo foo = new Foo();
System.out.println(foo instanceof EventListener); // true
foo.onEvent(new LoginEvent()); // Login
foo.onEvent(new LogoutEvent()); // Logout
}
}
The suppress warnings are there because we are "abusing" type erasure and delegating to two different event listeners based on the event concrete type. I have chosen to do it using a HashMap and the run-time Event class, but there are a lot of other possible implementations. You could use anonymous inner classes like #user949300 suggested, you could include a getEventType discriminator on the Event class to know what do to with each event and so on.
By using this code for all effects you are creating a single EventListener able to handle two kinds of events. The workaround is 100% self-contained (no need to expose the internal EventListeners).
Finally, there is one last issue that may bother you. At compile time Foo type is actually EventListener. Now, API methods out of your control may be expecting parametrized EventListeners:
public void addLoginListener(EventListener<LoginEvent> event) { // ...
// OR
public void addLogoutListener(EventListener<LogoutEvent> event) { // ...
Again, at run-time both of those methods deal with raw EventListeners. So by having Foo implement a raw interface the compiler will be happy to let you get away with just a type safety warning (which you can disregard with #SuppressWarnings("unchecked")):
eventSource.addLoginListener(foo); // works
While all of this may seem daunting, just repeat to yourself "The compiler is trying to trick me (or save me); there is no spoon <T>. Once you scratch your head for a couple of months trying to make legacy code written before Java 1.5 work with modern code full of type parameters, type erasure becomes second nature to you.
You need to use inner or anonymous classes. For instance:
class Foo {
public EventListener<X> asXListener() {
return new EventListener<X>() {
// code here can refer to Foo
};
}
public EventListener<Y> asYListener() {
return new EventListener<Y>() {
// code here can refer to Foo
};
}
}
This is not possible.
But for that you could create two different classes that implement EventListener interface with two different arguments.
public class Login implements EventListener<LoginEvent> {
public void onEvent(LoginEvent event) {
// TODO Auto-generated method stub
}
}
public class Logout implements EventListener<LogoutEvent> {
public void onEvent(LogoutEvent event) {
// TODO Auto-generated method stub
}
}
I've a parameterized interface:
public interface MyInterface<T> {
void run(T e);
}
And classes implementing the interface:
public class MyClass1 implements MyInterface<SomeOtherClass1> {
public void run(SomeOtherClass1 e) {
// do some stuff with e
}
}
public class MyClass2 implements MyInterface<SomeOtherClass2> {
public void run(SomeOtherClass2 e) {
// do some stuff with e
}
}
The number of different MyClass*X* is known and exhaustive, and there is only one instance of each MyClass*X*, so I would like to use an enum:
public enum MyEnum {
MY_CLASS_1,
MY_CLASS_2;
}
To be able to use MyEnum.MY_CLASS_1.run(someOtherClass1); for example (I would then have every instance of MyInterface in one same place). Is it even possible (and if yes, how)? Because I'm quite stuck for now...
What I tried yet:
public enum MyEnum {
MY_CLASS_1(new MyClass1()),
MY_CLASS_2(new MyClass2());
private MyInterface<?> instance;
private MyEnum(MyInterface<?> instance) {
this.instance = instance;
}
public void run(/* WhichType? */ e) {
instance.run(e);
}
}
In the above method, when using the type Object for the e parameter:
public void run(Object e) {
instance.run(e);
// ^^^
// The method run(capture#3-of ?) in the type MyInterface<capture#3-of ?> is not applicable for the arguments (Object)
}
The problem I think is with that private MyInterface<?> instance field: I need to know how is the instance parameterized, using something like private MyInterface<T> instance, but I can't find a working solution...
In short, I'm stuck ;)
PS: since the run methods bodies can be quite long, I'm trying to avoid anonymous classes within the enum:
public enum MyEnum {
MY_CLASS_1 {
/* any method, etc. */
},
MY_CLASS_2 {
/* any method, etc. */
},
}
MyEnum would then become totally unreadable.
It's not possible. That's one of the enum limitations I find most annoying, but all you can do is try to work around it (as you would have done in Java pre-5.0).
Only the enum itself can implement the interface and the generics must be specified at the enum level, so only Object or some common interface for those two would apply in your case.
Declaring any aspect that you want to treat polymorphically (the run() method, in your example) inside the enum itself (and overriding the behavior in each constant) is usually the best workaround. Of course, you need to loosen up your type safety requirements.
If you want to keep those strategies separated, you still need a run(Object) method inside the enum and that will be defined in each constant with some explicit cast, since you simply cannot have different method signatures per enum instance (or even if you can, they won't be visible as such from the outside).
A hint on how to trick the compiler, if you really want to do that rather than a redesign or explicit casts for each instance:
enum MyEnum implements MyInterface<Object> {
MY_CLASS_1(new MyClass1()),
MY_CLASS_2(new MyClass2());
// you may also drop generics entirely: MyInterface delegate
// and you won't need that cast in the constructor any more
private final MyInterface<Object> delegate;
MyEnum(MyInterface<?> delegate) {
this.delegate = (MyInterface<Object>) delegate;
}
#Override
public void run(Object e) {
delegate.run(e);
}
}
The above will work and you'll get a ClassCastException (as expected) if you try to use MyEnum.MY_CLASS_1.run() with something other than SomeOtherClass1.
As Costi points out, enums themselves can't be generic. However I think I can identify where you went wrong in your design:
There is only one instance of each MyClassX, so I would like to use
an enum:
public enum MyEnum {
MY_CLASS_1,
MY_CLASS_2;
}
You're saying that each of these classes is a singleton. So they should in fact each be an enum:
public enum MyClass1 implements MyInterface<SomeOtherClass1> {
INSTANCE;
#Override
public void run(SomeOtherClass1 e) {
// do some stuff with e
}
}
public enum MyClass2 implements MyInterface<SomeOtherClass2> {
INSTANCE;
#Override
public void run(SomeOtherClass2 e) {
// do some stuff with e
}
}
This makes more sense because if you think about it, you don't need to enumerate these two implementations, so there's no need for them to live together. It's enough to use Josh Bloch's enum pattern for each of them individually.
I've never been so good at design because there are so many different possibilities and they all have pros and cons and I'm never sure which to go with. Anyway, here's my problem, I have a need for many different loosly related classes to have validation. However, some of these classes will need extra information to do the validation. I want to have a method validate that can be used to validate a Object and I want to determine if an Object is validatable with an interface, say Validatable. The following are the two basic solutions I can have.
interface Validatable {
public void validate() throws ValidateException;
}
interface Object1Validatable {
public void validate(Object1Converse converse) throws ValidateException;
}
class Object1 implements Object1Validatable {
...
public void validate() throws ValidateException {
throw new UnsupportedOperationException();
}
}
class Object2 implements Validatable {
...
public void validate() throws ValidateException {
...
}
}
This is the first solution whereby I have a general global interface that something that's validatable implements and I could use validate() to validate, but Object1 doesn't support this so it's kind of defunc, but Object2 does support it and so may many other classes.
Alternatively I could have the following which would leave me without a top level interface.
interface Object1Validatable {
public void validate(Object1Converse converse) throws ValidateException;
}
class Object1 implements Object1Validatable {
...
public void validate(Object1Converse converse) throws ValidateException {
...
}
}
interface Object2Validatable {
public void validate() throws ValidateException;
}
class Object2 implements Object2Validatable {
...
public void validate() throws ValidateException {
...
}
}
I think the main problem I have is that I'm kind of stuck on the idea of having a top level interface so that I can at least say X or Y Object is validatable.
what about this :
interface Validatable {
void validate(Validator v);
}
class Object1 implements Validatable{
void validate(Validator v){
v.foo
v.bar
}
}
class Object1Converse implements Validator{
//....
}
class Object2 implements Validatable{
void validate(Validator v){
//do whatever you need and ingore validator ?
}
}
What do you care if Object2 receives an unneeded argument ? if it is able to operatee correctly without it it can just ignore it right ?
If you are worried about introducing an unneeded dependency between object2 and Object1Converse then simply specify an interface to decouple them and use that as the validator.
Now I must add that having a mixed model where you have both object able to self validate and object which need external state information to validate sounds weird.
care to illustrate ?
Perhaps the apache commons validator project would be useful here - either directly or as a model for how to attack your problem. They effectively have a parallel set of objects that do the validation - so there is no interface on the objects, just the presence/absence of a related validator for the object/class.
This is in C#, but the same ideas can certainly be implemented in many other languages.
public class MyClass {
//Properties and methods here
}
public class MyClassValidator : IValidator<MyClass> {
IList<IValidatorError> IValidator.Validate(MyClass obj) {
//Perform some checks here
}
}
//...
public void RegisterValidators() {
Validators.Add<MyClassValidator>();
}
//...
public void PerformSomeLogic() {
var myobj = new MyClass { };
//Set some properties, call some methods, etc.
var v = Validators.Get<MyClass>();
if(v.GetErrors(myobj).Count() > 0)
throw new Exception();
SaveToDatabase(myobj);
}
As simple solution to the "can an object be validated" problem is to add a third interface.
This third interface is an empty one that parents both of the others, meaning you can just check against that interface (Assuming you aren't worried about someone spoofing being validate-able), and then iteratively check against the possible validation interfaces if you need to actually validate.
Example:
interface Validateable
{
}
interface EmptyValidateable inherits Validateable //Or is it implements?
{
void validate() throws ValidateException;
}
interface Objectvalidateable inherits Validateable
{
void validate(Object validateObj);
}