abstract contract ERC721WithOverrides is ERC721, ERC721Enumerable, ERC721URIStorage, ERC721Burnable, Ownable {
    /**
        Overriding functions below due to extensions ERC721URIStorage and IERC721Enumerable now being their own contracts which each inheirt ERC721. 
        This change was introduced in openzeppelin 4.0.0
     */

    function _beforeTokenTransfer(address from, address to, uint256 tokenId)
        internal
        override(ERC721, ERC721Enumerable)
    {
        super._beforeTokenTransfer(from, to, tokenId);
    }

    function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {
        super._burn(tokenId);
    }

    function tokenURI(uint256 tokenId)
        public
        view
        override(ERC721, ERC721URIStorage)
        returns (string memory)
    {
        return super.tokenURI(tokenId);
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC721, ERC721Enumerable)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }

}
function _beforeTokenTransfer(address from, address to, uint256 tokenId)
    internal
    override(ERC721, ERC721Enumerable)
{
    super._beforeTokenTransfer(from, to, tokenId);
}

/**
 Overriding functions below due to extensions ERC721URIStorage and IERC721Enumerable now being their own contracts which each inheirt ERC721.
 This change was introduced in openzeppelin 4.0.0
 */