Uændret interface - Immutable interface
I objektorienteret programmering er " uforanderlig interface " et mønster til at designe et uforanderligt objekt . Det uforanderlige interface-mønster involverer at definere en type, der ikke tilvejebringer nogen metoder, der muterer tilstand. Objekter, der henvises til af den type, ses ikke at have nogen mutbar tilstand og forekommer uforanderlige.
Eksempel
Java
Overvej en Java-klasse, der repræsenterer et to-dimensionelt punkt.
public class Point2D {
private int x;
private int y;
public Point2D(int x, int y) { this.x = x; this.y = y; }
public int getX() { return this.x; }
public int getY() { return this.y; }
public void setX(int newX) { this.x = newX; }
public void setY(int newY) { this.y = newY; }
}
Klassen Point2D er mutabel: dens tilstand kan ændres efter konstruktion ved at påberåbe sig en af sætningsmetoderne ( setX()eller setY()).
En uforanderlig grænseflade til Point2D kunne defineres som:
public interface ImmutablePoint2D {
public int getX();
public int getY();
}
Ved at få Point2D til at implementere ImmutablePoint2D, kunne klientkode nu henvise til en type, der ikke har mutationsmetoder, og som derfor forekommer uforanderlig. Dette demonstreres i følgende eksempel:
ImmutablePoint2D point = new Point2D(0,0); // a concrete instance of Point2D is referenced by the immutable interface
int x = point.getX(); // valid method call
point.setX(42); // compile error: the method setX() does not exist on type ImmutablePoint2D
Ved kun at henvise til den uforanderlige grænseflade er det ikke gyldigt at kalde en metode, der muterer tilstanden af det konkrete objekt.
Fordele
- Kommunikerer klart den uforanderlige hensigt af typen.
- I modsætning til typer, der implementerer Immutable Wrapper- mønsteret, behøver ikke at "annullere" mutationsmetoder ved at udstede en " No Operation " -instruktion eller kaste en undtagelse af runtime, når en mutationsmetode påberåbes.
Ulemper
- Det er muligt for tilfælde, der henvises til af den uforanderlige interface-type, at blive støbt til deres konkrete, mutable type og få deres tilstand muteret. For eksempel:
public void mutate(ImmutablePoint2D point) { ((Point2D)point).setX(42); // this call is legal, since the type has // been converted to the mutable Point2D class }
- Betonklasser skal eksplicit erklære, at de implementerer den uforanderlige grænseflade. Dette er muligvis ikke muligt, hvis betonklassen "hører til" tredjepartskode, for eksempel hvis den er indeholdt i et bibliotek.
- Objektet er ikke rigtig uforanderligt og er derfor ikke egnet til brug i datastrukturer, der er afhængige af uforanderlighed som hashkort. Og objektet kunne ændres samtidigt fra den "mutable side".
- Nogle kompilatoroptimeringer, der er tilgængelige for uforanderlige objekter, er muligvis ikke tilgængelige for mutable objekter.
Alternativer
Et alternativ til det uforanderlige interface-mønster er det uforanderlige indpakningsmønster .
Vedvarende datastrukturer er effektivt uforanderlige, mens de tillader ændrede visninger af sig selv.