JE_17 - Používejte rozhraní pouze k definování typů

Když třída implementuje nějaké rozhraní, slouží toto rozhraní jako typ, s jehož pomocí se lze odkazovat na instance dané třídy. Skutečnost, že třída implementuje určité rozhraní, by tedy měla říkat něco o tom, co může klient dělat s instancemi dané třídy. Je nevhodné definovat rozhraní pro jakýkoli jiný účel.

Jedním druhem rozhraní, který tomuto testu nevyhovuje, jsou takzvaná konstantní rozhraní. Takové rozhraní neobsahuje žádné metody; skládá se čistě ze statických finálních atributů, z nichž každý exportuje nějakou konstantu. Třídy, používající tyto konstanty, implementují takové rozhraní proto, aby nemusely kvalifikovat názvy konstant s názvem třídy. Zde máme příklad:

// Vzor konstantího rozhraní - nepoužívejte!
public interface PhysicalConstants {
	// Avogadrovo číslo (1 / mol)
	static final double AVOGADROS_NUMBER = 6.02214199e23;
	
	// Boltzmannova konstanta
	static final double BOLTZMANN_CONSTANT = 1.3806503e-23;

	// Hmotnost elektronu
	static final double ELECTRON_MASS = 9.10938188e-31;
}

Takový vzor konstantního rozhraní představuje slabé používání rozhraní. To, že nějaká třída používá interně určitá rozhraní, je implementačním detailem. Implementování konstantního rozhraní způsobuje pronikání této implementační podrobnosti do API exportovaného danou třídou. Uživatele dané třídy vůbec nemusí zajímat, že tato třída implementuje nějaké rozhraní konstant. Dokonce ho to může zmást. navíc představuje závazek: Bude-li v další verzi třída upravena tak, že již nemusí tyto konstanty používat, musíte přesto jejich rozhraní implementovat, aby byla zajištěna binární kompatibilita. Pokud nějaká nefinální třída implementuje konstantní rozhraní, všechny její podtřídy budou mít oblasti názvů zamořené konstantami v tomto rozhraní.

V knihovnách platformy Java existuje několik konstantních rozhraní, jako je například java.io.ObjectStreamConstants. Tato rozhraní je zapotřebí chápat jako anomality a nelze je napodobovat.

Chcete-li exportovat nějaké konstanty, pak máte několik rozumných možností. Jsou-li tyto konstanty úzce svázány s nějakou existující třídou nebo rozhraním, pak byste je měli přidat do dané třídy nebo rozhraní. Například všechny numerické obalové třídy knihoven platformy programovacího jazyka Java, jakými jsou Integer a Float, exportují konstanty MIN_VALUE a MAX_VALUE. Je-li nejlepší pohlížet na konstanty jako na členy nějakého výčtového typu, pak byste je měli exportovat prostřednictvím typově zabezpečené výčtové třídy (rada 21) (typ enum byl přidán do jazyka Java ve verzi 1.5, pozn. překladatele). Jinak byste měli tyto konstanty exportovat v nějaké pomocné třídě, z níž nelze vytvářet instance (rada 3. Zde máme verzi výše uvedeného příkladu s pomocnou třídou PhysicalConstants:

// Pomocná třída konstant
public class PhysicalConstants {
	
	private PhysicalConstants() {
	}

	public static final double AVOGADROS_NUMBER = 6.02214199e23;
	public static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
	public static final double ELECTRON_MASS = 9.10938188e-31;
}

Třebaže verze s pomocnou třídou PhysicalConstants vyžaduje po kientech kvlifikaci názvů konstant pomocí názvu třídy, je to jen malá cena za rozumná API. Je možné, že jazyk nakonec umožní importování statických atributů (tak se také stalo ve verzi 1.4, pozn. překladatele). V současné době můžete minimalizovat potřebu rozsáhlého typování tak, že si uložíte často používané konstnty do lokálních proměnných nebo soukromých statických atributů, například:

private static final double PI = Math.PI;

Celkově můžeme říci, že rozhraní by měla být používána pouze k definování typů. Neměli byste je používat k exportování konstant.