Parfois, vous devez écrire un constructeur qui peut échouer. Par exemple, disons que je veux instancier un objet avec un chemin de fichier, quelque chose comme
obj = new Object("/home/user/foo_file")
Tant que le chemin pointe sur un fichier approprié tout va bien. Mais si la chaîne n'est pas une trajectoire valide, les choses devraient casser. Mais comment?
Vous pourriez:
Je suppose que les "meilleures pratiques" de différentes langages de programmation mettront en œuvre cela différemment. Par exemple, je pense que Objc préfère (2). Mais (2) serait impossible à mettre en œuvre en C++ où les constructeurs doivent avoir annulé comme type de retour. Dans ce cas, je suppose que (1) est utilisé.
Dans votre langage de programmation de choix, pouvez-vous montrer comment vous géreriez ce problème et expliquer pourquoi?
Il n'est jamais bon de compter sur un constructeur pour faire le saleté. En outre, c'est aussi non claire à un autre programmeur, que ce travail soit effectué dans le constructeur, sauf indication contraire de la documentation explicite (et que l'utilisateur de la classe l'ait lu ou a été dit. .
Par exemple (en C #):
public Sprite
{
public Sprite(string filename)
{
}
}
Que se passe-t-il si l'utilisateur ne veut pas tout de suite charger le fichier? Et si elles veulent faire la mise en cache à la demande du fichier? Ils ne peuvent pas. Vous pouvez penser à mettre un argument bool loadFile
dans le constructeur, mais cela rend ce désordre en désordre comme vous toujours besoin d'une méthode Load()
méthode pour charger le fichier.
Compte tenu du scénario actuel, il sera plus flexible et plus clair pour les utilisateurs de la classe pour le faire:
Sprite sprite = new Sprite();
Sprite.Load("mario.png");
Ou alternativement (pour quelque chose comme une ressource):
Sprite sprite = new Sprite();
Sprite.Source = "mario.png";
Sprite.Cache();
// On demand caching of file contents.
public void Cache()
{
if (image == null)
{
try
{
image = new Image.FromFile(Source);
}
catch(...)
{
}
}
}
En Java, vous pouvez utiliser des exceptions ou utiliser le motif d'usine, ce qui vous permettrait de renvoyer NULL.
À Scala, vous pouvez retourner une option [FOO] d'une méthode d'usine. Cela fonctionnerait dans Java aussi, mais serait plus lourd.
Jeter une exception.
NULL doit être vérifié si vous pouvez le retourner (et ce ne sera pas vérifié)
C'est ce que fait des exceptions vérifiées. Vous savez que cela pourrait échouer. Les appelants doivent gérer cela.
Dans C++, les constructeurs sont utilisés pour créer/initialiser des membres de la classe.
Il n'y a pas de bonne réponse à cette question. Mais ce que j'ai observé jusqu'à présent, c'est que la plupart du temps est le client (ou celui qui va utiliser votre API) qui choisit comment vous devez gérer ce genre de choses.
Parfois, ils pourraient vous demander d'allouer toutes les ressources que l'objet pourrait avoir besoin sur le constructeur et lancer une exception si quelque chose échoue (abandonnant la création de l'objet), ou ne fais rien de cela sur le constructeur, et Assurez-vous que la création réussira toujours, laissant ces tâches pour une fonction de membre membre à faire.
Si c'est à vous de choisir le comportement, Exceptions sont la manière C++ par défaut pour les erreurs de traitement et vous devez les utiliser quand vous le pouvez.
Vous pouvez également instancier l'objet sans paramètres ou avec uniquement des paramètres qui ne sont sûrs de ne jamais échouer, puis vous utilisez une fonction d'initialisation ou une méthode à partir de laquelle vous pouvez projeter une exception en toute sécurité ou faire ce que vous souhaitez.