diff --git a/src/main/java/de/prob2/jupyter/Parameter.java b/src/main/java/de/prob2/jupyter/Parameter.java
index 5368a3c229b9e950870de1ab3ff91283f1ec7a69..06d282527a53d0b6cb9ec2356d9a4fbfd040870c 100644
--- a/src/main/java/de/prob2/jupyter/Parameter.java
+++ b/src/main/java/de/prob2/jupyter/Parameter.java
@@ -3,11 +3,9 @@ package de.prob2.jupyter;
 import java.util.List;
 import java.util.Optional;
 
-import com.google.common.base.MoreObjects;
-
 import org.jetbrains.annotations.NotNull;
 
-public abstract class Parameter<T> {
+public interface Parameter<T> {
 	public static final class SplitResult {
 		private final @NotNull String splitArg;
 		private final @NotNull String remainingArgString;
@@ -67,99 +65,85 @@ public abstract class Parameter<T> {
 		public abstract T validate(final @NotNull Parameter<T> param, final @NotNull List<@NotNull String> argValues);
 	}
 	
-	public static class RequiredSingle extends Parameter<@NotNull String> {
-		public RequiredSingle(final @NotNull String identifier, final boolean repeating, final @NotNull Parameter.Splitter splitter, final @NotNull Parameter.Validator<@NotNull String> validator) {
-			super(identifier, repeating, splitter, validator);
-		}
-	}
+	public interface RequiredSingle extends Parameter<@NotNull String> {}
 	
-	public static class OptionalSingle extends Parameter<@NotNull Optional<String>> {
-		public OptionalSingle(final @NotNull String identifier, final boolean repeating, final @NotNull Parameter.Splitter splitter, final @NotNull Parameter.Validator<@NotNull Optional<String>> validator) {
-			super(identifier, repeating, splitter, validator);
-		}
-	}
+	public interface OptionalSingle extends Parameter<@NotNull Optional<String>> {}
 	
-	public static class Multiple extends Parameter<@NotNull List<@NotNull String>> {
-		public Multiple(final @NotNull String identifier, final boolean repeating, final @NotNull Parameter.Splitter splitter, final @NotNull Parameter.Validator<@NotNull List<@NotNull String>> validator) {
-			super(identifier, repeating, splitter, validator);
-		}
-	}
+	public interface Multiple extends Parameter<@NotNull List<@NotNull String>> {}
 	
-	private final @NotNull String identifier;
-	private final boolean repeating;
-	private final @NotNull Parameter.Splitter splitter;
-	private final @NotNull Parameter.Validator<T> validator;
+	public abstract @NotNull String getIdentifier();
 	
-	protected Parameter(final @NotNull String identifier, final boolean repeating, final @NotNull Parameter.Splitter splitter, final @NotNull Parameter.Validator<T> validator) {
-		super();
-		
-		this.identifier = identifier;
-		this.repeating = repeating;
-		this.splitter = splitter;
-		this.validator = validator;
-	}
-	
-	public @NotNull String getIdentifier() {
-		return this.identifier;
-	}
-	
-	public boolean isRepeating() {
-		return this.repeating;
-	}
-	
-	public @NotNull Parameter.Splitter getSplitter() {
-		return this.splitter;
-	}
+	public abstract boolean isRepeating();
 	
-	public @NotNull Parameter.Validator<T> getValidator() {
-		return this.validator;
-	}
+	public abstract @NotNull Parameter.Splitter getSplitter();
 	
-	@Override
-	public String toString() {
-		return MoreObjects.toStringHelper(this)
-			.add("identifier", this.getIdentifier())
-			.add("repeating", this.isRepeating())
-			.add("splitter", this.getSplitter())
-			.add("validator", this.getValidator())
-			.toString();
-	}
+	public abstract @NotNull Parameter.Validator<T> getValidator();
 	
 	public static Parameter.RequiredSingle required(final String identifier) {
-		return new Parameter.RequiredSingle(identifier, false, Parameter.Splitter.REGULAR, Parameter.Validator.EXACTLY_ONE);
+		return new ParameterBase.RequiredSingle(identifier);
 	}
 	
 	public static Parameter.OptionalSingle optional(final String identifier) {
-		return new Parameter.OptionalSingle(identifier, false, Parameter.Splitter.REGULAR, Parameter.Validator.ZERO_OR_ONE);
+		return new ParameterBase.OptionalSingle(identifier);
 	}
 	
 	public static Parameter.Multiple requiredMultiple(final String identifier) {
-		return new Parameter.Multiple(identifier, true, Parameter.Splitter.REGULAR, Parameter.Validator.ONE_OR_MORE);
+		return new ParameterBase.Multiple(identifier) {
+			@Override
+			public @NotNull Parameter.Validator<@NotNull List<@NotNull String>> getValidator() {
+				return Parameter.Validator.ONE_OR_MORE;
+			}
+		};
 	}
 	
 	public static Parameter.Multiple optionalMultiple(final String identifier) {
-		return new Parameter.Multiple(identifier, true, Parameter.Splitter.REGULAR, Parameter.Validator.ZERO_OR_MORE);
+		return new ParameterBase.Multiple(identifier) {
+			@Override
+			public @NotNull Parameter.Validator<@NotNull List<@NotNull String>> getValidator() {
+				return Parameter.Validator.ZERO_OR_MORE;
+			}
+		};
 	}
 	
 	public static Parameter.RequiredSingle requiredRemainder(final String identifier) {
-		return new Parameter.RequiredSingle(identifier, false, Parameter.Splitter.REMAINDER, Parameter.Validator.EXACTLY_ONE);
+		return new ParameterBase.RequiredSingle(identifier) {
+			@Override
+			public @NotNull Parameter.Splitter getSplitter() {
+				return Parameter.Splitter.REMAINDER;
+			}
+		};
 	}
 	
 	public static Parameter.OptionalSingle optionalRemainder(final String identifier) {
-		return new Parameter.OptionalSingle(identifier, false, Parameter.Splitter.REMAINDER, Parameter.Validator.ZERO_OR_ONE);
+		return new ParameterBase.OptionalSingle(identifier) {
+			@Override
+			public @NotNull Parameter.Splitter getSplitter() {
+				return Parameter.Splitter.REMAINDER;
+			}
+		};
 	}
 	
 	public static Parameter.RequiredSingle body(final String identifier) {
-		return new Parameter.RequiredSingle(identifier, false, argString -> {
-			throw new AssertionError("Splitter of a body parameter should never be used");
-		}, (param, argValues) -> {
-			if (argValues.isEmpty()) {
-				throw new UserErrorException("Missing required body " + param.getIdentifier());
-			} else if (argValues.size() > 1) {
-				throw new AssertionError("Body " + param.getIdentifier() + " appeared more than once, this should never happen!");
+		return new ParameterBase.RequiredSingle(identifier) {
+			@Override
+			public @NotNull Parameter.Splitter getSplitter() {
+				return argString -> {
+					throw new AssertionError("Splitter of a body parameter should never be used");
+				};
 			}
 			
-			return argValues.get(0);
-		});
+			@Override
+			public @NotNull Parameter.Validator<@NotNull String> getValidator() {
+				return (param, argValues) -> {
+					if (argValues.isEmpty()) {
+						throw new UserErrorException("Missing required body " + param.getIdentifier());
+					} else if (argValues.size() > 1) {
+						throw new AssertionError("Body " + param.getIdentifier() + " appeared more than once, this should never happen!");
+					}
+					
+					return argValues.get(0);
+				};
+			}
+		};
 	}
 }
diff --git a/src/main/java/de/prob2/jupyter/ParameterBase.java b/src/main/java/de/prob2/jupyter/ParameterBase.java
new file mode 100644
index 0000000000000000000000000000000000000000..85228fdfd1be77f195826b8d64c42ad09107d919
--- /dev/null
+++ b/src/main/java/de/prob2/jupyter/ParameterBase.java
@@ -0,0 +1,73 @@
+package de.prob2.jupyter;
+
+import java.util.List;
+import java.util.Optional;
+
+import com.google.common.base.MoreObjects;
+
+import org.jetbrains.annotations.NotNull;
+
+abstract class ParameterBase<T> implements Parameter<T> {
+	static class RequiredSingle extends ParameterBase<@NotNull String> implements Parameter.RequiredSingle {
+		protected RequiredSingle(final @NotNull String identifier) {
+			super(identifier);
+		}
+		
+		@Override
+		public @NotNull Parameter.Validator<@NotNull String> getValidator() {
+			return Parameter.Validator.EXACTLY_ONE;
+		}
+	}
+	
+	static class OptionalSingle extends ParameterBase<@NotNull Optional<String>> implements Parameter.OptionalSingle {
+		protected OptionalSingle(final @NotNull String identifier) {
+			super(identifier);
+		}
+		
+		@Override
+		public @NotNull Parameter.Validator<@NotNull Optional<String>> getValidator() {
+			return Parameter.Validator.ZERO_OR_ONE;
+		}
+	}
+	
+	abstract static class Multiple extends ParameterBase<@NotNull List<@NotNull String>> implements Parameter.Multiple {
+		protected Multiple(final @NotNull String identifier) {
+			super(identifier);
+		}
+		
+		@Override
+		public boolean isRepeating() {
+			return true;
+		}
+	}
+	
+	private final @NotNull String identifier;
+	
+	protected ParameterBase(final @NotNull String identifier) {
+		super();
+		
+		this.identifier = identifier;
+	}
+	
+	@Override
+	public @NotNull String getIdentifier() {
+		return this.identifier;
+	}
+	
+	@Override
+	public boolean isRepeating() {
+		return false;
+	}
+	
+	@Override
+	public @NotNull Parameter.Splitter getSplitter() {
+		return Parameter.Splitter.REGULAR;
+	}
+	
+	@Override
+	public String toString() {
+		return MoreObjects.toStringHelper(this)
+			.add("identifier", this.getIdentifier())
+			.toString();
+	}
+}