An experimental/theoretical question concerning any OOP language (Java, C#, Typescript, etc..)
Usually, when implementing an interface in a class, one has to override all the functions of that interface in the class by having to write the code for each function from that interface. And every class that implements this interface has to have its own code for those functions. Suppose we have an interface called Test that has a function called foo() in which I want the following code System.out.println("This is an interface function");.Usually one has to make an interface and declare the function and then writes the code in every implementing class
But what if there is some "theoretical" way of having all of the function written in the interface and every implementing class can just call it without having to override. Something like the following (using Java as a base language):
interface Test {
public foo() {
System.out.println("Test log.")
}
}
class Class1 implements Test {
constructor() {}
}
class Class2 implements Test {
constructor() {}
}
class Main {
public static void main() {
Class1 f1 = new Class1();
Class2 f2 = new Class2();
f1.foo();
f2.foo();
}
}
Java has this feature since Java 8. Interfaces can have default implementations where the class is free to override them, but not required to do so.
interface Test {
default void foo() {
System.out.println("Test log.");
}
}
Related
As mention here: if a function in an interface has no body it is abstract by default. But there is nothing about interface's function with body.
Example:
interface MyInterface {
fun foo() { print("Something") }
fun bar()
}
fun main(args: Array<String>) {
println(MyInterface::foo.javaMethod)
println(MyInterface::bar.javaMethod)
}
Output will be:
public abstract void MyInterface.foo()
public abstract void MyInterface.bar()
How it's possible, that method with defined body is abstract?
This has to do with the way default methods in Kotlin interfaces are implemented. The foo and bar methods in your interface really are both abstract.
However, there is an inner class inside the interface that looks something like this (simplified):
public interface MyInterface {
void foo();
void bar();
public static final class DefaultImpls {
public static void foo() {
System.out.print("Something");
}
}
}
This class is the one that contains the default implementations of any functions that you gave a body to inside the interface.
Then, if you create a class that implements this interface, and you don't override the foo method:
class MyClass: MyInterface {
override fun bar() {
println("MyClass")
}
}
Then you get one generated automatically, which just calls the implementation inside DefaultImpls:
public final class MyClass implements MyInterface {
public void bar() {
System.out.println("MyClass");
}
public void foo() {
MyInterface.DefaultImpls.foo();
}
}
You can find all these details by using the bytecode viewer that comes with the Kotlin plugin (Tools -> Kotlin -> Show Kotlin Bytecode, and then the Decompile option).
I had following code
public interface IFoo
{
void Execute();
}
public abstract class FooBar: IFoo
{
public void Execute()
{
OnExecute();
}
public abstract void OnExecute();
}
and following test case to test the Execute() method
[Fact]
public void When_execute_method_called_Expect_executionTime_is_set()
{
var sutMethod = A.Fake<FooBar>();
A.CallTo(sutMethod).
Where(x => x.Method.Name == "OnExecute").
Invokes(x => Thread.Sleep(100)));
sutMethod.Execute();
Assert.NotEqual(0, sutMethod.Result.ExecutionTime.Ticks);
}
sutMethod.Execute(); call would go to FooBar.Execute()
later I decided to make the interface into an abstract class
public abstract class IFoo
{
public abstract void Execute();
}
public abstract class FooBar:IFoo
{
public override void Execute()
{
OnExecute();
}
public abstract void OnExecute();
}
Now sutMethod.Execute(); call does not invoke FooBar.Execute()
I thought FakeItEasy would handles interface and abstract classes as equal.What am I missing?
Update
# Blair Conrad provided the reasoning for the behaviour
Is it possible to make minimal changes to the test case to get the original behaviour back?
thanks
The difference is due to the overrideability of the method Execute on FooBar.
FakeItEasy can only override virtual members, abstract members, or interface members.
In your original example, when IFooBar is an interface and FooBar implements it, Execute is a concrete method. It's not virtual, nor is it abstract. Thus FakeItEasy can't intercept calls to it, and the original method is executed.
Once you change IFooBar to an abstract class, you have an abstract IFooBar.Execute, which you override in FooBar. As such, FooBar.Execute is now virtual and can be intercepted by FakeItEasy. Which it does, so your implementation is not called.
Following addition help solve the issue
A.CallTo(() => sutMethod.Execute()).CallsBaseMethod();
This calls the virtual method Executeof FooBar
Suppose we have a default method in a interface,
in implementing class if we need to add some additional logic besides the one the default method already does we have to copy the whole method? is there any possibility to reuse default method... like we do with abstract class
super.method()
// then our stuff...
You can invoke it like this:
interface Test {
public default void method() {
System.out.println("Default method called");
}
}
class TestImpl implements Test {
#Override
public void method() {
Test.super.method();
// Class specific logic here.
}
}
This way, you can easily decide which interface default method to invoke, by qualifying super with the interface name:
class TestImpl implements A, B {
#Override
public void method() {
A.super.method(); // Call interface A method
B.super.method(); // Call interface B method
}
}
This is the case why super.method() won't work. As it would be ambiguous call in case the class implements multiple interfaces.
I want to run the same JUnit tests for different interface implementations. I found a nice solution with the #Parameter option:
public class InterfaceTest{
MyInterface interface;
public InterfaceTest(MyInterface interface) {
this.interface = interface;
}
#Parameters
public static Collection<Object[]> getParameters()
{
return Arrays.asList(new Object[][] {
{ new GoodInterfaceImpl() },
{ new AnotherInterfaceImpl() }
});
}
}
This test would be run twice, first with the GoodInterfaceImpl then with the AnotherInterfaceImpl class. But the problem is I need for most of the testcases a new object. A simplified example:
#Test
public void isEmptyTest(){
assertTrue(interface.isEmpty());
}
#Test
public void insertTest(){
interface.insert(new Object());
assertFalse(interface.isEmpty());
}
If the isEmptyTest is run after the insertTest it fails.
Is there an option to run automatically each testcase with a new instance of an implementation?
BTW: Implementing a clear() or reset()-method for the interface is not really an options since I would not need it in productive code.
Here is another approach with the Template Method pattern:
The interface-oriented tests go into the base class:
public abstract class MyInterfaceTest {
private MyInterface myInterface;
protected abstract MyInterface makeContractSubject();
#Before
public void setUp() {
myInterface = makeContractSubject();
}
#Test
public void isEmptyTest(){
assertTrue(myInterface.isEmpty());
}
#Test
public void insertTest(){
myInterface.insert(new Object());
assertFalse(myInterface.isEmpty());
}
}
For each concrete class, define a concrete test class:
public class GoodInterfaceImplTest extends MyInterfaceTest {
#Override
protected MyInterface makeContractSubject() {
// initialize new GoodInterfaceImpl
// insert proper stubs
return ...;
}
#Test
public void additionalImplementationSpecificStuff() {
...
}
}
A slight advantage over #Parameter is that you get the name of the concrete test class reported when a test fails, so you know right away which implementation failed.
Btw, in order for this approach to work at all, the interface must be designed in a way which allows testing by the interface methods only. This implies state-based testing -- you cannot verify mocks in the base test class. If you need to verify mocks in implementation-specific tests, these tests must go into the concrete test classes.
Create a factory interface and implementations, possibly only in your test hierarchy if you don't need such a thing in production, and make getParameters() return a list of factories.
Then you can invoke the factory in a #Before annotated method to get a new instance of your actual class under test for each test method run.
Just in case somebody reaches here(like I did), looking for testing multiple implementations of the same interface in .net you could see one of the approaches that I was using in one of the projects here
Below is what we are following in short
The same test project dll is run twice using vstest.console, by setting an environment variable. Inside the test, (either in the assembly initialize or test initialize) register the appropriate implementations into a IoC container, based on the environment variable value.
In Junit 5 you could do:
#ParameterizedTest
#MethodSource("myInterfaceProvider")
void test(MyInterface myInterface) {}
static Stream<MyInterface> myInterfaceProvider() {
return Stream.of(new ImplA(), new ImplB());
}
interface MyInterface {}
static class ImplA implements MyInterface {}
static class ImplB implements MyInterface {}
what can I do to make the abstract function work in the emaillogger class?
class EmailLogger extends Zend_Log_Writer_Abstract
and I want to use the function _write
protected function _write($event)
{
$this->_events[] = $this->_formatter->format($event);
}
then I got this error
Class EmailLogger contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Zend_Log_FactoryInterface::factory)
I am not really sure what to do here
I try'd to use implements Zend_Log_FactoryInterface, but it diddn't work
thanks, Richard
Zend_Log_Writer_Abstract implements Zend_Log_FactoryInterface which has the following code:
static public function factory($config);
This forces the Zend_Log_Writer_Abstract and any child classes to also have a factory method. To satisfy this requirement, you could put in a wrapper method which calls the parent method:
class EmailLogger extends Zend_Log_Writer_Abstract
{
// Add this method in conjunction to what you already have in your class
public static function factory($config)
{
parent::factory($config);
}
}