protected function getSlice($start, $stop, $step)
    {
        $length = $this->length();
        $step = (isset($step)) ? $step : 1;

        if ($step === 0)
        {
            throw new InvalidArgumentException('Slice step cannot be 0');
        }

        if (isset($start))
        {
            $start = $this->adjustBoundary($length, $start, $step);
        }
        else
        {
            $start = ($step > 0) ? 0 : $length - 1;
        }

        if (isset($stop))
        {
            $stop = $this->adjustBoundary($length, $stop, $step);
        }
        else
        {
            $stop = ($step > 0) ? $length : -1;
        }

        // Return an empty string if the set of indices would be empty
        if (($step > 0 && $start >= $stop) || ($step < 0 && $start <= $stop))
        {
            return new static('');
        }

        // Return the substring if step is 1
        if ($step === 1)
        {
            return $this->cut($start, $stop - $start);
        }

        // Otherwise iterate over the slice indices
        $str = '';
        foreach ($this->getIndices($start, $stop, $step) as $index)
        {
            $str .= (isset($this[$index])) ? $this[$index] : '';
        }

        return new static($str);
    }