What does ObjectFactory.named() do, and when do you use Named types in Gradle?
answer
- named(Type, "value") → Named instance
- Usage/Category/LibraryElements attributes
- typed string for variant matching
- Attribute.of + custom Named type
- managed instance, equality by name
basics
~10 sobjects.named(Type, "value") creates an instance of a Named interface subtype carrying that string name. It's used for attribute values like Usage, Category, or custom variant attributes in dependency resolution.
solid answer
~40 s`ObjectFactory.named(Class<T>, String)` builds an instance of a type that extends Gradle's `Named` interface, using the given string as its name. `Named` is the contract for *typed string-keyed* objects — it just guarantees a `getName()`. You use it primarily for **attributes** in dependency management: attribute keys like `Usage`, `Category`, `LibraryElements`, `Bundling`, and `TargetJvmVersion` take `Named`-typed values, and you select a value with `objects.named(Usage::class.java, Usage.JAVA_API)`. Because `Usage` is a `Named` interface (not an enum), Gradle generates the instance, which lets the value participate in attribute *compatibility/disambiguation* rules during variant matching. You also define your **own** attribute by declaring an `Attribute.of("my.attr", MyType::class.java)` where `MyType : Named`, then setting it with `attributes.attribute(MY_ATTR, objects.named(MyType::class.java, "premium"))`. Beyond attributes, any domain object that needs a stable string identity in a container can implement `Named`.
code
kotlin · 10 linesinterface Environment : Named
val ENV_ATTR = Attribute.of("com.acme.environment", Environment::class.java)
configurations.consumable("prodElements") {
attributes.attribute(
ENV_ATTR,
objects.named(Environment::class.java, "production")
)
}go deeper
Recognize objects.named() exists for attribute values like Usage.
Use named() with built-in attributes (Usage, Category) when configuring configurations.
Define custom attributes with custom Named types and understand why typed values matter for matching.
Govern an org-wide attribute scheme and compatibility/disambiguation rules for variant-aware publishing/consumption.
## The Named interface `Named` is a tiny Gradle interface: ```java public interface Named { String getName(); } ``` It models a value that is essentially *a typed string*. You don't implement it by hand for attribute use — you ask `ObjectFactory` to make one: ```kotlin val apiUsage = objects.named(Usage::class.java, Usage.JAVA_API) ``` Gradle generates a concrete instance whose `getName()` returns `"java-api"`. ## Why not just use a String or enum? Gradle's **attribute** system underpins variant-aware dependency resolution. Attributes are typed key/value pairs attached to configurations and published variants. When Gradle resolves a dependency it matches the consumer's requested attributes against producers' variants, applying **compatibility rules** (is value B acceptable when A is requested?) and **disambiguation rules** (pick the best of several candidates). For this to work, attribute values must be *typed objects* the rules can reason about — hence `Named` types rather than bare strings. Using a typed `Named` also catches mismatches at the type level and lets two plugins agree on the same attribute semantics. ## Built-in attributes that take Named values - `Usage` — `java-api`, `java-runtime` - `Category` — `library`, `platform`, `documentation` - `LibraryElements` — `jar`, `classes`, `resources` - `Bundling` — `external`, `embedded`, `shadowed` Each is a `Named` subtype with string constants; you materialize the wanted value via `objects.named(...)`. ## Defining a custom attribute ```kotlin interface Quality : Named val QUALITY = Attribute.of("com.acme.quality", Quality::class.java) configurations.named("runtimeClasspath") { attributes.attribute(QUALITY, objects.named(Quality::class.java, "premium")) } ``` Producers tag their variants with the same attribute; Gradle's matching engine then routes consumers to the right variant. You can register compatibility/disambiguation rules on `dependencies.attributesSchema` to control fallbacks. ## How it ties back to ObjectFactory `named()` is just another factory method on `ObjectFactory`, alongside `property()`, `fileProperty()`, and `newInstance()`. It produces a *managed* `Named` instance so that — like other managed objects — it integrates cleanly with Gradle's model (equality by name, serializable for the configuration cache, usable in attribute containers). ## Gotchas - Two `named()` instances of the same type and name are considered equal for attribute matching. - Don't roll your own `Named` impl with `object : Named` for attributes — use `objects.named()` so Gradle controls instantiation and equality.
- Why does Gradle use Named types for attributes instead of plain strings?Attributes drive variant matching, which needs typed values so compatibility and disambiguation rules can reason about them and so two plugins share the same semantics. Named instances are also managed (stable equality, CC-serializable).
- How do you create a brand-new attribute with a custom Named type?Define an interface extending Named, create Attribute.of("name", MyType::class.java), then set it on a configuration/variant via attributes.attribute(attr, objects.named(MyType::class.java, "value")).
saying these in an interview costs you the question
- Implementing Named by hand (object : Named) for attribute values instead of objects.named().
- Confusing Named (string identity for attributes/containers) with NamedDomainObjectContainer registration.
- Claiming attributes can be plain strings.