diff --git a/src/Capabilities/ReadonlyClass.php b/src/Capabilities/ReadonlyClass.php
new file mode 100644
index 0000000000000000000000000000000000000000..63e762a4e8a8521c0a000c3c0204b8880f73f72f
--- /dev/null
+++ b/src/Capabilities/ReadonlyClass.php
@@ -0,0 +1,29 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Grifart\ClassScaffolder\Capabilities;
+
+use Grifart\ClassScaffolder\ClassInNamespace;
+use Grifart\ClassScaffolder\Definition\ClassDefinition;
+
+final class ReadonlyClass implements Capability
+{
+	public function applyTo(
+		ClassDefinition $definition,
+		ClassInNamespace $draft,
+		?ClassInNamespace $current,
+	): void
+	{
+		$classType = $draft->getClassType();
+		$classType->setReadOnly();
+
+		CapabilityTools::checkIfAllFieldsArePresent($definition, $classType);
+
+		foreach ($definition->getFields() as $field) {
+			$fieldName = $field->getName();
+			$property = CapabilityTools::getProperty($classType, $fieldName);
+			$property->setPublic();
+		}
+	}
+}
diff --git a/src/Capabilities/functions.php b/src/Capabilities/functions.php
index e4877fedf885d5728ab0ad37f07ba1d7bf2f211b..628824e9a2689b498366eea6f5d3efa7b31decdb 100644
--- a/src/Capabilities/functions.php
+++ b/src/Capabilities/functions.php
@@ -54,6 +54,10 @@ function properties(): Properties {
 	return new Properties();
 }
 
+function readonlyClass(): ReadonlyClass {
+	return new ReadonlyClass();
+}
+
 function readonlyProperties(): ReadonlyProperties {
 	return new ReadonlyProperties();
 }
diff --git a/tests/Capabilities/ReadonlyClassTest.expected.phps b/tests/Capabilities/ReadonlyClassTest.expected.phps
new file mode 100644
index 0000000000000000000000000000000000000000..28b36e652bb4306a4c765f1a3c43298aec518cfc
--- /dev/null
+++ b/tests/Capabilities/ReadonlyClassTest.expected.phps
@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * Do not edit. This is generated file. Modify definition file instead.
+ */
+
+declare(strict_types=1);
+
+namespace RootNamespace\SubNamespace;
+
+use Iterator;
+
+final readonly class ClassName
+{
+	/**
+	 * @param Iterator<string, int[]> $field2
+	 */
+	public function __construct(
+		public ?string $field1,
+		public Iterator $field2,
+	) {
+	}
+}
diff --git a/tests/Capabilities/ReadonlyClassTest.phpt b/tests/Capabilities/ReadonlyClassTest.phpt
new file mode 100644
index 0000000000000000000000000000000000000000..9d48c7934b25663e1a6d49d8a0ff607de5797543
--- /dev/null
+++ b/tests/Capabilities/ReadonlyClassTest.phpt
@@ -0,0 +1,23 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Grifart\ClassScaffolder\Test\Capabilities;
+
+use function Grifart\ClassScaffolder\Capabilities\constructorWithPromotedProperties;
+use function Grifart\ClassScaffolder\Capabilities\readonlyClass;
+
+require __DIR__ . '/../bootstrap.php';
+
+final class ReadonlyClassTest extends CapabilityTestCase
+{
+	protected function getCapabilities(): array
+	{
+		return [
+			constructorWithPromotedProperties(),
+			readonlyClass(),
+		];
+	}
+}
+
+(new ReadonlyClassTest())->run();