public function like(...$types): self
    {
        if ($this->isFinalized) {
            throw new FinalizedMockException();
        }

        $final = [];

        foreach ($types as $type) {
            if (is_array($type)) {
                if (!empty($type)) {
                    if (array_values($type) === $type) {
                        $final = array_merge($final, $type);
                    } else {
                        $final[] = $type;
                    }
                }
            } else {
                $final[] = $type;
            }
        }

        $toAdd = [];

        if (!$this->parentClassName) {
            $parentClassNames = [];
        } else {
            $parentClassNames = [$this->parentClassName];
        }

        $parentClassName = '';
        $definitions = [];

        foreach ($final as $type) {
            if (is_string($type)) {
                try {
                    $type = new ReflectionClass($type);
                } catch (ReflectionException $e) {
                    throw new InvalidTypeException($type, $e);
                }
            } elseif (is_array($type)) {
                foreach ($type as $name => $value) {
                    if (!is_string($name)) {
                        throw new InvalidDefinitionException($name, $value);
                    }
                }

                $definitions[] = $type;

                continue;
            } else {
                throw new InvalidTypeException($type);
            }

            if ($type->isAnonymous()) {
                throw new AnonymousClassException();
            }

            $isTrait = $type->isTrait();

            if (!$isTrait && $type->isFinal()) {
                throw new FinalClassException($type->getName());
            }

            if (!$isTrait && !$type->isInterface()) {
                $parentClassNames[] = $parentClassName = $type->getName();
            }

            $toAdd[] = $type;
        }

        $parentClassNames = array_unique($parentClassNames);
        $parentClassCount = count($parentClassNames);

        if ($parentClassCount > 1) {
            throw new MultipleInheritanceException($parentClassNames);
        }

        foreach ($toAdd as $type) {
            $name = strtolower($type->getName());

            if (!isset($this->types[$name])) {
                $this->types[$name] = $type;
            }
        }

        if ($parentClassCount > 0) {
            $this->parentClassName = $parentClassName;
        }

        foreach ($definitions as $definition) {
            $this->define($definition);
        }

        return $this;
    }