[[inheritance_full]]

== Inheritance and specialization in {cdi_full}

[[specialize_managed_bean]]

=== Specializing a managed bean

In addition to rules defined in <<managed_beans>>, the following rules apply.

If a bean class of a managed bean X is annotated `@Specializes`, then the bean class of X must directly extend the bean class of another managed bean Y.
Then X _directly specializes_ Y, as defined in <<specialization>>.

If the bean class of X does not directly extend the bean class of another managed bean, the container automatically detects the problem and treats it as a definition error.

For example, `MockLoginAction` directly specializes `LoginAction`:

[source, java]
----
public class LoginAction { ... }
----

[source, java]
----
@Mock @Specializes
public class MockLoginAction extends LoginAction { ... }
----

[[specialize_producer_method]]

=== Specializing a producer method

In addition to rules defined in <<producer_method>>, the following rules apply.

If a producer method X is annotated `@Specializes`, then it must be non-static and directly override another producer method Y.
Then X _directly specializes_ Y, as defined in <<specialization>>.

If the method is static or does not directly override another producer method, the container automatically detects the problem and treats it as a definition error.

[source, java]
----
@Mock
public class MockShop extends Shop {

   @Override @Specializes
   @Produces
   PaymentProcessor getPaymentProcessor() {
      return new MockPaymentProcessor();
   }

   @Override @Specializes
   @Produces
   List<Product> getProducts() {
      return PRODUCTS;
   }

   ...

}
----

[[specialization]]

=== Specialization

If two beans both support a certain bean type, and share at least one qualifier, then they are both eligible for injection to any injection point with that declared type and qualifier.

Consider the following beans:

[source, java]
----
@Default @Asynchronous
public class AsynchronousService implements Service {
    ...
}
----

[source, java]
----
@Alternative
public class MockAsynchronousService extends AsynchronousService {
    ...
}
----

Suppose that the `MockAsynchronousService` alternative is selected, as defined in <<selection>>:

[source, java]
----
@Alternative @Priority(jakarta.interceptor.Interceptor.Priority.APPLICATION+100)
public class MockAsynchronousService extends AsynchronousService {
    ...
}
----

Then, according to the rules of <<unsatisfied_and_ambig_dependencies>>, the following ambiguous dependency is resolvable, and so the attribute will receive an instance of `MockAsynchronousService`:

[source, java]
----
@Inject Service service;
----

However, the following attribute will receive an instance of `AsynchronousService`, even though `MockAsynchronousService` is a selected alternative, because `MockAsynchronousService` does not have the qualifier `@Asynchronous`:

[source, java]
----
@Inject @Asynchronous Service service;
----

This is a useful behavior in some circumstances, however, it is not always what is intended by the developer.

The only way one bean can completely override a second bean at all injection points is if it implements all the bean types and declares all the qualifiers of the second bean.
However, if the second bean declares a producer method or observer method, then even this is not enough to ensure that the second bean is never called!

To help prevent developer error, the first bean may:

* directly extend the bean class of the second bean, or
* directly override the producer method, in the case that the second bean is a producer method, and then


explicitly declare that it _specializes_ the second bean.

[source, java]
----
@Specializes
public class MockAsynchronousService extends AsynchronousService {
    ...
}
----

When an enabled bean, as defined in <<enablement>>, specializes a second bean, we can be certain that the second bean is never instantiated or called by the container.
Even if the second bean defines a producer or observer method, the method will never be called.

[[direct_and_indirect_specialization]]

==== Direct and indirect specialization

The annotation `@jakarta.enterprise.inject.Specializes` is used to indicate that one bean _directly specializes_ another bean, as defined in <<specialize_managed_bean>> and <<specialize_producer_method>>.

Formally, a bean X is said to _specialize_ another bean Y if there is either:

* direct specialization, where X directly specializes Y, or
* transitive specialization, where a bean Z exists, such that X directly specializes Z and Z specializes Y.


Then X will inherit the qualifiers and bean name of Y:

* the qualifiers of X include all qualifiers of Y, together with all qualifiers declared explicitly by X, and
* if Y has a bean name, the bean name of X is the same as the bean name of Y.


Furthermore, X must have all the bean types of Y.
If X does not have some bean type of Y, the container automatically detects the problem and treats it as a definition error.

If Y has a bean name and X declares a bean name explicitly the container automatically detects the problem and treats it as a definition error.

For example, the following bean would have the inherited qualifiers `@Default` and `@Asynchronous`:

[source, java]
----
@Mock @Specializes
public class MockAsynchronousService extends AsynchronousService {
    ...
}
----

If `AsynchronousService` declared a bean name:

[source, java]
----
@Default @Asynchronous @Named("asyncService")
public class AsynchronousService implements Service{
    ...
}
----

Then the bean name would also automatically be inherited by `MockAsynchronousService`.

If an interceptor or decorator is annotated `@Specializes`, non-portable behavior results.

