I'm starting using Fluent Assertions and I like it a lot, but wonder if it's possible to extend the existing tests in a general way like this:
add method hasSizeAtLeast(int limit) in GroupAssert
add method startsWithIgnoringCase(String prefix) in StringAssert
use alternatives like x.either().isIn(someSet).or().isNull()
These are just examples what I could need soon. I can do some workaround for each of them, but then I lose the readability and the easy of use of the fluent interface.
My last example is meant to throw iff both x.isIn(someSet) and x.isNull() do.
Here is a post by the author about opening up his API for extending assertions on already handled types. Lesson #1 in particular discusses the change to un-finalize classes. The post also gives an example of sub-classing StringAssert as MyStringAssert.
However, it looks like you cannot extend classes such as StringAssert in a way that maintains the "fluency" of the API. The StringAssert class isn't final, but still it doesn't allow you to parameterize its type (i.e. the "this" type that's returned by methods in StringAssert itself) in subclasses. For example, let's say you add a method checkFoo in MyStringAssert. As you discovered, the following is invalid because the original StringAssert methods return StringAssert:
new MyStringAssert("abcd").contains("a").checkFoo(); // compile-time error!
You only can call your subclass's methods first, which is valid but kind of lame:
new MyStringAssert("abcd").checkFoo().contains("a"); // compiles
You might consider contacting the author, or even submitting a patch to his git project. A possible solution would be to add the parameterized type back into StringAssert, and also provide the StringAssert concrete type via an anonymous subclass within Assertions.assertThat(String), which is the recommended entry point anyway. Then, everybody else can subclass StringAssert as you described. I haven't tested this suggestion either, but it seems to make sense...
Related
One of the most useful features of Java 8 are the new default methods on interfaces. There are essentially two reasons (there may be others) why they have been introduced:
Providing actual default implementations. Example: Iterator.remove()
Allowing for JDK API evolution. Example: Iterable.forEach()
From an API designer's perspective, I would have liked to be able to use other modifiers on interface methods, e.g. final. This would be useful when adding convenience methods, preventing "accidental" overrides in implementing classes:
interface Sender {
// Convenience method to send an empty message
default final void send() {
send(null);
}
// Implementations should only implement this method
void send(String message);
}
The above is already common practice if Sender were a class:
abstract class Sender {
// Convenience method to send an empty message
final void send() {
send(null);
}
// Implementations should only implement this method
abstract void send(String message);
}
Now, default and final are obviously contradicting keywords, but the default keyword itself would not have been strictly required, so I'm assuming that this contradiction is deliberate, to reflect the subtle differences between "class methods with body" (just methods) and "interface methods with body" (default methods), i.e. differences which I have not yet understood.
At some point of time, support for modifiers like static and final on interface methods was not yet fully explored, citing Brian Goetz:
The other part is how far we're going to go to support class-building
tools in interfaces, such as final methods, private methods, protected
methods, static methods, etc. The answer is: we don't know yet
Since that time in late 2011, obviously, support for static methods in interfaces was added. Clearly, this added a lot of value to the JDK libraries themselves, such as with Comparator.comparing().
Question:
What is the reason final (and also static final) never made it to Java 8 interfaces?
This question is, to some degree, related to What is the reason why “synchronized” is not allowed in Java 8 interface methods?
The key thing to understand about default methods is that the primary design goal is interface evolution, not "turn interfaces into (mediocre) traits". While there's some overlap between the two, and we tried to be accommodating to the latter where it didn't get in the way of the former, these questions are best understood when viewed in this light. (Note too that class methods are going to be different from interface methods, no matter what the intent, by virtue of the fact that interface methods can be multiply inherited.)
The basic idea of a default method is: it is an interface method with a default implementation, and a derived class can provide a more specific implementation. And because the design center was interface evolution, it was a critical design goal that default methods be able to be added to interfaces after the fact in a source-compatible and binary-compatible manner.
The too-simple answer to "why not final default methods" is that then the body would then not simply be the default implementation, it would be the only implementation. While that's a little too simple an answer, it gives us a clue that the question is already heading in a questionable direction.
Another reason why final interface methods are questionable is that they create impossible problems for implementors. For example, suppose you have:
interface A {
default void foo() { ... }
}
interface B {
}
class C implements A, B {
}
Here, everything is good; C inherits foo() from A. Now supposing B is changed to have a foo method, with a default:
interface B {
default void foo() { ... }
}
Now, when we go to recompile C, the compiler will tell us that it doesn't know what behavior to inherit for foo(), so C has to override it (and could choose to delegate to A.super.foo() if it wanted to retain the same behavior.) But what if B had made its default final, and A is not under the control of the author of C? Now C is irretrievably broken; it can't compile without overriding foo(), but it can't override foo() if it was final in B.
This is just one example, but the point is that finality for methods is really a tool that makes more sense in the world of single-inheritance classes (generally which couple state to behavior), than to interfaces which merely contribute behavior and can be multiply inherited. It's too hard to reason about "what other interfaces might be mixed into the eventual implementor", and allowing an interface method to be final would likely cause these problems (and they would blow up not on the person who wrote the interface, but on the poor user who tries to implement it.)
Another reason to disallow them is that they wouldn't mean what you think they mean. A default implementation is only considered if the class (or its superclasses) don't provide a declaration (concrete or abstract) of the method. If a default method were final, but a superclass already implemented the method, the default would be ignored, which is probably not what the default author was expecting when declaring it final. (This inheritance behavior is a reflection of the design center for default methods -- interface evolution. It should be possible to add a default method (or a default implementation to an existing interface method) to existing interfaces that already have implementations, without changing the behavior of existing classes that implement the interface, guaranteeing that classes that already worked before default methods were added will work the same way in the presence of default methods.)
In the lambda mailing list there are plenty of discussions about it. One of those that seems to contain a lot of discussion about all that stuff is the following: On Varied interface method visibility (was Final defenders).
In this discussion, Talden, the author of the original question asks something very similar to your question:
The decision to make all interface members public was indeed an
unfortunate decision. That any use of interface in internal design
exposes implementation private details is a big one.
It's a tough one to fix without adding some obscure or compatibility
breaking nuances to the language. A compatibility break of that
magnitude and potential subtlety would seen unconscionable so a
solution has to exist that doesn't break existing code.
Could reintroducing the 'package' keyword as an access-specifier be
viable. It's absence of a specifier in an interface would imply
public-access and the absence of a specifier in a class implies
package-access. Which specifiers make sense in an interface is unclear
- especially if, to minimise the knowledge burden on developers, we have to ensure that access-specifiers mean the same thing in both
class and interface if they're present.
In the absence of default methods I'd have speculated that the
specifier of a member in an interface has to be at least as visible as
the interface itself (so the interface can actually be implemented in
all visible contexts) - with default methods that's not so certain.
Has there been any clear communication as to whether this is even a
possible in-scope discussion? If not, should it be held elsewhere.
Eventually Brian Goetz's answer was:
Yes, this is already being explored.
However, let me set some realistic expectations -- language / VM
features have a long lead time, even trivial-seeming ones like this.
The time for proposing new language feature ideas for Java SE 8 has
pretty much passed.
So, most likely it was never implemented because it was never part of the scope. It was never proposed in time to be considered.
In another heated discussion about final defender methods on the subject, Brian said again:
And you have gotten exactly what you wished for. That's exactly what
this feature adds -- multiple inheritance of behavior. Of course we
understand that people will use them as traits. And we've worked hard
to ensure that the the model of inheritance they offer is simple and
clean enough that people can get good results doing so in a broad
variety of situations. We have, at the same time, chosen not to push
them beyond the boundary of what works simply and cleanly, and that
leads to "aw, you didn't go far enough" reactions in some case. But
really, most of this thread seems to be grumbling that the glass is
merely 98% full. I'll take that 98% and get on with it!
So this reinforces my theory that it simply was not part of the scope or part of their design. What they did was to provide enough functionality to deal with the issues of API evolution.
It will be hard to find and identify "THE" answer, for the resons mentioned in the comments from #EJP : There are roughly 2 (+/- 2) people in the world who can give the definite answer at all. And in doubt, the answer might just be something like "Supporting final default methods did not seem to be worth the effort of restructuring the internal call resolution mechanisms". This is speculation, of course, but it is at least backed by subtle evidences, like this Statement (by one of the two persons) in the OpenJDK mailing list:
"I suppose if "final default" methods were allowed, they might need rewriting from internal invokespecial to user-visible invokeinterface."
and trivial facts like that a method is simply not considered to be a (really) final method when it is a default method, as currently implemented in the Method::is_final_method method in the OpenJDK.
Further really "authorative" information is indeed hard to find, even with excessive websearches and by reading commit logs. I thought that it might be related to potential ambiguities during the resolution of interface method calls with the invokeinterface instruction and and class method calls, corresponding to the invokevirtual instruction: For the invokevirtual instruction, there may be a simple vtable lookup, because the method must either be inherited from a superclass, or implemented by the class directly. In contrast to that, an invokeinterface call must examine the respective call site to find out which interface this call actually refers to (this is explained in more detail in the InterfaceCalls page of the HotSpot Wiki). However, final methods do either not get inserted into the vtable at all, or replace existing entries in the vtable (see klassVtable.cpp. Line 333), and similarly, default methods are replacing existing entries in the vtable (see klassVtable.cpp, Line 202). So the actual reason (and thus, the answer) must be hidden deeper inside the (rather complex) method call resolution mechanisms, but maybe these references will nevertheless be considered as being helpful, be it only for others that manage to derive the actual answer from that.
I wouldn't think it is neccessary to specify final on a convienience interface method, I can agree though that it may be helpful, but seemingly the costs have outweight the benefits.
What you are supposed to do, either way, is to write proper javadoc for the default method, showing exactly what the method is and is not allowed to do. In that way the classes implementing the interface "are not allowed" to change the implementation, though there are no guarantees.
Anyone could write a Collection that adheres to the interface and then does things in the methods that are absolutely counter intuitive, there is no way to shield yourself from that, other than writing extensive unit tests.
We add default keyword to our method inside an interface when we know that the class extending the interface may or may not override our implementation. But what if we want to add a method that we don't want any implementing class to override? Well, two options were available to us:
Add a default final method.
Add a static method.
Now, Java says that if we have a class implementing two or more interfaces such that they have a default method with exactly same method name and signature i.e. they are duplicate, then we need to provide an implementation of that method in our class. Now in case of default final methods, we can't provide an implementation and we are stuck. And that's why final keyword isn't used in interfaces.
Suppose we have implemented the Decorator Pattern as in the image below. With the CondimentDecorator class, the Beverage class can be decorated. The methods cost() and getDescription() will take care for that.
When creating a decorated Beverage like below, calling the method getName() won't work on the decorated object. In order to make this work, this method should also be placed in the class CondimentDecorator and delegate the call to the composed beverage variable.
Beverage b = new Milk(new Espresso("A very nice espresso"));
b.getName() // returns null
When having a lot of methods which don't need decoration, all of these should also be placed in CondimentDecorator to simply delegate. So the question is: What is a neat (generally accepted) way to solve this 'problem'?
The generally accepted approach to this 'problem' in a statically typed language like Java or C# (yes, C# is not quite statically typed, I know about DLR, and dynamic) is to have the decorated methods delegate to the decorated object explicitly. This solution has the obvious benefits of simplicity and explicitness.
In your example, if you don't override getName it means that you want to change the behaviour of the decorated object, which is exactly the purpose of the decorator pattern.
If you would choose to delegate to the decorated object by default then it would appear as if inheritance was broken, since CondimentDecorator inherits from Beverage but does not use the methods of base class.
Then, to change this behaviour, you would somehow need to define the methods that are not delegated to decorated object, but should work "as usual inheritance".
That would be not obvious and very messy.
That being said, what you want to achieve should be possible in Java.
For instance in .NET you could do this in the following ways, and I believe Java has something similar
By generating dynamic runtime proxies that use inheritance to dynamically modify the behaviour of the object, see Castle Dynamic Proxy
By using a MSIL rewriting technique that rewrites your itermediate code at compile time to modify it, for example see Fody - Method decorator
Additionally, check out how prototypical inheritance works in JavaScript - that behaviour is very similar to what you're trying to achieve
In your case if only few operation1() it is ok to add a delegate call to CondimentDecorator. If only few call() needs decoration then could make a decorator when needed, like:
DecoratorFactory.make(new Milk(new Espresso("A very nice espresso"))).getDescription();
or
CondimentDecorator.getDescription(new Milk(new Espresso("A very nice espresso")));
Key: patterns serve you.
I have noticed in SONAR that I have a violation that is called IllegalType in my java Code. I looked for this and in Checkstyle explain about it this :
Checks that particular class are never used as types in variable declarations, return values or parameters. Includes a pattern check that by default disallows abstract classes.
Rationale: Helps reduce coupling on concrete classes. In addition abstract classes should be thought of a convenience base class implementations of interfaces and as such are not types themselves.
But I don't understand really why is this a problem in my code. If anyone can explain me better maybe with an example it could be great!. Thanks at all.
What Aaron Digulla said in his comments is a good practice for sure. However I also found this IllegalType issue with my own Abstract Classes (instead of interfaces) which don't seem to me to be pretty clear. I understand the benefits of using intefaces insteaf of classes, and I also understand that abstract classes are partially classes (so much more a class than a interface) but I don't see the benefits of this rule, as I can find cases where I can return a concrete class (no abstract) which is a superclass of what I'm actually returning.
Not all violations that Sonar finds are for everyone. The check IllegalType (docs) tries to make sure you don't use classes that most developers deem "broken" in some way like Vector (use ArrayList instead).
Other classes shouldn't be used as a return type. Always return List instead of ArrayList, Set instead of HashSet, Map instead of HashMap - that way, consumers of your code don't know any unnecessary details about your implementation. If you find you need to replace HashMap with TreeMap (or vice versa) in a method, that will be much more simple if you don't have to change all the places as well where this method was called.
Generally, the check isn't a problem as such (your code works) but fixing those will make your code easier to maintain in the future.
When I was programming a Form Validator in PHP, when creating new methods, I needed to increase the number of arguments in old methods.
When I was learning Java, when I read that extends is to not touch previously tested, working code, I thought I shouldn't have increased the number of arguments in the old methods, but overridden the old methods with the new methods.
Imagine if you are to verify if a field is empty in one part of the form, in an other and in yet an other.
If the arguments are different, you'll overload isEmpty, but, if the arguments are equal, is it right to use isEmpty, isEmpty2, isEmpty3, three classes and one isEmpty per class or, if both are wrong, what should I have done?
So the question is:
If I need different behaviors for a method isEmpty which receives the same number arguments, what should I do?
Use different names? ( isEmpty, isEmpty2, isEmpty3 )
Have three classes with a single isEmpty method?
Other?
If that's the question then I think you should use:
When they belong to the same logical unit ( they are of the same sort of validation ) but don't use numbers as version, better is to name them after what they do: isEmptyUser, isEmptyAddress, isEmptyWhatever
When the validator object could be computed in one place and passed around during the program lifecycle. Let's say: Validator v = Validator.getInstance( ... ); and then use it as : validator.isEmpty() and let polymorphism to it's job.
Alternatively you could pack the arguments in one class and pass it to the isEmpty method, although you'll end up with pretty much the same problem of the name. Still it's easier to refactor from there and have the new class doing the validation for you.
isEmpty( new Arguments(a,b,c ) ); => arguments.isEmpty();
The Open/Closed Principle [usually attributed to Bertrand Meyer] says that "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification". This might be the principle that you came across in your Java days. In real life this applies to completed code where the cost of modification, re-testing and re-certification outweighs the benefit of the simplicity gained by making a direct change.
If you are changing a method because it needs an additional argument, you might choose to use the following steps:
Copy the old method.
Remove the implementation from the copy.
Change the signature of the original method to add the new argument.
Update the implementation of the original method to use the new argument.
Implement the copy in terms of the new method with a default value for the argument.
If your implementation language doesn't support method overloading then the principle is the same but you need to find a new name for the new method signature.
The advantage of this approach is that you have added the new argument to the method, and your existing client code will continue to compile and run.
This works well if there is an obvious default for the new argument, and less well if there isn't.
Since java 5 you can use variable list of arguments as in void foo(Object ... params)
You will need to come up with creative names for your methods since you can't overload methods that have same type and number of arguments (or based on return type). I actually personally prefer this to overloading anyway. So you can have isEmpty and isEmptyWhenFoo and isEmptyWhenIHaveTheseArguments (well meybe not the last one :)
Not sure if this actually answers your question, but the best way to think about OO in "real life" is to think of the Nygaard Classification:
ObjectOrientedProgramming. A program execution is regarded as a physical model, simulating the behavior of either a real or imaginary part of the world.
So how would you build a physical device to do what you are trying to do in code? You'd probably have some kind of "Form" object, and the form object would have little tabs or bits connected to it to represent the different Form variables, and then you would build a Validator object that would take the Form object in a slot and then flash one light if the form was valid and another if it was invalid. Or your Validator could take a Form object in one slot and return a Form object out (possibly the same one), but modified in various ways (that only the Validator understood) to make it "valid". Or maybe a Validator is part of a Form, and so the Form has this Validator thingy sticking out of it...
My point is, try to imagine what such a machine would look like and how it would work. Then think of all of the parts of that machine, and make each one an object. That's how "object-oriented" things work in "real life", right?
With that said, what is meant by "extending" a class? Well, a class is a "template" for objects -- each object instance is made by building it from a class. A subclass is simply a class that "inherits" from a parent class. In Java at least, there are two kinds of inheritance: interface inheritance and implementation inheritance. In Java, you are allowed to inherit implementation (actual method code) from at most one class at a time, but you can inherit many interfaces -- which are basically just collections of attributes that someone can see from outside your class.
Additionally, a common way of thinking about OO programming is to think about "messages" instead of "method calls" (in fact, this is the original term invented by Alan Kay for Smalltalk, which was the first language to actually be called "object-oriented"). So when you send an isEmpty message to the object, how do you want it to respond? Do you want to be able to send different arguments with the isEmpty message and have it respond differently? Or do you want to send the isEmpty message to different objects and have them respond differently? Either are appropriate answers, depending on the design of your code.
Instead having one class providing multiple versions of isEmpty with differing names, try breaking down your model into a finer grained pieces the could be put together in more flexible ways.
Create an interface called Empty with
one method isEmpty(String value);
Create implemntations of this
interface like EmptyIgnoreWhiteSpace
and EmptyIgnoreZero
Create FormField
class that have validation methods
which delegate to implementations of
Empty.
Your Form object will have
instances of FormField which will
know how to validate themselves.
Now you have a lot of flexibility, you can combine your Empty implemenation classes to make new classes like EmptyIgnoreWhiteSpaceAndZero. You can use them in other places that have nothing to do with form field validation.
You don't have have have multple similarly named methods polluting your object model.
If I have a class that needs to implement an interface but one or more of the methods on that interface don't make sense in the context of this particular class, what should I do?
For example, lets say I'm implementing an adapter pattern where I want to create a wrapper class that implements java.util.Map by wrapping some immutable object and exposing it's data as key/value pairs. In this case the methods put and putAll don't make sense as I have no way to modify the underlying object. So the question is what should those methods do?
Any method that cannot be implemented according to the semantics of the interface should throw an UnsupportedOperationException.
That depends on your business case. 2 options:
Do nothing.
Throw an UnsupportedOperationException.
Use whichever makes more sense. If you do nothing, you are not obeying the contract of the interface. However, throwing a runtime exception can wreak havoc on the calling code. Thus, the decision will have to be made based on how you will be using the class. Another option would be to use a simpler or different interface, if possible.
Do note that the Java library goes the exception route in the specific case of read-only collections.
It was noted below that UnsupportedOperationException is a part of the java collections framework. If your situation is outside of collections, and the semantics bother you, you can roll your own NotImplementedException, or if you are already using commons-lang, you could use theirs.
That read-only collection already provided by Java throw the UnsupportedOperationException during write operations is already an unfortunate design hack. The collection classes should have been written with separate read-only and write-only interfaces that are both inherited by the full read-write interface. Then you know what you're getting.
Your two choices are really only:
Do nothing.
Throw an exception.
Both have disadvantages. In the first case, by having an empty method, you could mislead the programmer into thinking something happened to your data. The second case breaks the whole idea of polymorphism inherent in interfaces.
Note that UnsupportedOperationException is only OK because of the particular property of the Java Collections Framework, that implementations are permitted to "goof off" implementing part of the interface because they're immutable.
So it's fine for put() (assuming all the mutator methods do the same thing), but a Map which throws UnsupportedOperationException from the size() method would just be broken. If you're trying to implement a kind of map which doesn't know how big it is, you may be in trouble (although sometimes you can return Integer.MAX_VALUE).
Also note that the class documentation for UnsupportedOperationException says that it is part of the Java Collections Framework. Outside the collections framework, throwing UnsupportedOperationException is not be expected and could lead to client code that plain doesn't work. Sure, it's a RuntimeException, but just because you can throw it doesn't mean that your method will work if it always does.
Instead you could either refactor the interface (perhaps splitting it in two), or else rethink why this class is claiming to be a Foo when it plainly isn't, since it can't do the things that Foos are defined to be able to do.