Maison > Questions et réponses > le corps du texte
呃…… 标题不太好。让我在问题描述里解释一下。
让我以 Android 开发中一个简单的例子说明:在一个 Activity
中有多个可点击的按钮时,很多人会这么写:
public class ExampleActivity extends Activity implements OnClickListener {
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_example);
findViewById(R.id.first_button).setOnClickListener(this);
findViewById(R.id.second_button).setOnClickListener(this);
}
@Override
public void onClick(final View v) {
switch (v.getId()) {
case R.id.first_button:
// bla bla bla
break;
case R.id.second_button:
// bra bra bra
}
}
}
事实上,Android 官方有些 sample 里面也是这么写的。然而在我看来,这么写代码是非常不优雅的,因为一个 OnClickListener
的实现,只应该关注和点击事件本身相关的内容,它的含义和 Activity
的含义是截然无关的,让同一个类继承/实现他们,会使得这个类的含义变得不清晰。同时,这样还给 ExampleActivity
类增加了一个 public
的方法,削弱了这个类的封闭性。
所以如果像下面这样,会好不少:
public class ExampleActivity extends Activity {
private OnClickListener onClickListener = new OnClickListener() {
@Override
public void onClick(final View v) {
switch (v.getId()) {
case R.id.first_button:
// bla bla bla
break;
case R.id.second_button:
// bra bra bra
}
}
};
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_example);
findViewById(R.id.first_button).setOnClickListener(onClickListener);
findViewById(R.id.second_button).setOnClickListener(onClickListener);
}
}
这样写体现了 composition over inheritance 的思想。它避免了上面的所有问题,看起来舒服得多。
不过,这样还是让阅读代码时很不方便——看到 onCreate
里面时,还不得不经常滚动到声明 onClickListener
的地方去,并且在 onClick
中艰难的寻找真正和某个特定按钮相关的代码。当然这两个问题之前那个版本也都无法避免。
另一件糟糕的事情是,不同按钮的 listener 逻辑很可能是相对独立的,放到同一个 onClickListener
里,还是很丑陋。
所以为了进一步避免这几个问题,我一向都是用下面这样的写法:
public class ExampleActivity extends Activity {
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_example);
findViewById(R.id.first_button).setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
// bla bla bla
}
});
findViewById(R.id.second_button).setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
// bra bra bra
}
});
}
}
这样的话,不同逻辑间相对独立,看起来非常舒服,便于阅读,并且让我找回了写 JavaScript 的舒畅感觉(划掉)。
那么问题来了:为什么有的人不使用最后一种写法呢,倒反是使用第一种写法呢?
巴扎黑2017-04-17 18:02:20
Je suis également d’accord avec la deuxième façon d’écrire. Vous avez déjà évoqué ses avantages, je n’entrerai donc pas dans les détails. Mais je me suis toujours demandé pourquoi les exemples officiels de Google avaient été écrits de la première manière. Plus tard, j'ai vu un paragraphe dans la documentation Android, qui disait en gros : La création d'objets en Java coûte en fait très cher. Si tous les écouteurs sont créés individuellement, cela le fera. le programme génère beaucoup de frais supplémentaires. C'est pourquoi Google a choisi d'utiliser le même objet pour effectuer toute la surveillance. Cela est principalement dû au fait que les performances des premiers appareils Android n'étaient pas particulièrement bonnes et qu'ils ne pouvaient économiser que sur ces détails. Désormais, les appareils n'ont plus besoin de trop s'en soucier. ceux-ci, donc utiliser la deuxième méthode est également inoffensif.
PHP中文网2017-04-17 18:02:20
Personnellement, je préfère la dernière façon d'écrire, et si OnClickListener
a beaucoup à faire, je pourrais l'écrire séparément en tant que classe nommée.
Cependant, il existe en effet de nombreuses premières façons d'écrire. Je suppose qu'une des raisons est que les exemples sont trompeurs, car les exemples de codes sont généralement relativement petits, donc il n'y a aucun problème à écrire de cette façon, et le code ne le sera pas. très long, mais dans les affaires réelles, le code peut être beaucoup plus lourd; une autre raison peut être que certaines personnes pensent que l'écriture de cours est trop lourde. Bien sûr, en fait, l'écriture de cours n'est pas nécessairement plus lourde que les méthodes d'écriture. base théorique et pratique. Certaines personnes ont fait des analyses, donc je n'en dirai pas plus.
En C#, les délégués sont utilisés pour implémenter les événements Click de différents boutons, et chaque délégué correspond à une certaine XxxxButton_Click
méthode du formulaire actuel (s'il s'agit d'un programme WinForm, les applications ASP.NET sont similaires). façon d'écrire Il est hérité de l'ancien VB/VC. Bien entendu, le fait que UI Designer veuille faire cela ne peut être exclu. En raison de la popularité de Lambda, de plus en plus de personnes commencent à utiliser la troisième méthode d'écriture similaire à l'affiche originale, mais ce n'est pas une interface, c'est juste un Lambda - et il y a un principe, sans utiliser UI Designer pour générer situation de code.
Pourquoi parler de C#, car Java a réalisé la supériorité de Lambda, il a donc également implémenté Lambda, simulant la délégation de C# sous la forme d'une interface à méthode unique, donc la troisième façon d'écrire peut être plus simple.
Cependant, tout a deux côtés. Lambda est pratique mais apporte aussi quelques inconvénients, surtout lorsque la logique est complexe. Par conséquent, pour le traitement d'événements avec une logique plus complexe, je recommande toujours d'écrire une classe de traitement distincte, qui peut être une implémentation d'une interface d'événement (telle que l'implémentation d'OnClickListener), ou une classe de traitement métier indépendante (ou un ensemble de classes associées). . Appelez en une phrase dans onClick (comme new Business(params).Go()
)
怪我咯2017-04-17 18:02:20
Composition sur héritage
Comment comprenez-vous cela ? La composition vaut-elle mieux que l’héritage ? En raison de la mauvaise réputation de l’héritage, chacun rejette désormais de manière préventive l’héritage lorsqu’il le voit.
Mais est-ce vraiment le cas ? Je ne suis pas d'accord.
Les relations d'objet dans OO sont grossièrement divisées en plusieurs relations, telles que l'association, la dépendance, la combinaison, l'agrégation, l'héritage et la généralisation. Ces relations stipulent la relation entre les objets.
C'est-à-dire que la relation entre les objets est quelle que soit la relation. Pour être précis, il n'y a absolument aucune combinaison à cause du concept d'héritage, je ne sais pas car l'héritage est facile à mettre en œuvre, donc tout le monde aime le faire. Utiliser l'héritage pour réutiliser. En fait, l'essence de ce qui précède est due à une abstraction insuffisante de l'objet.
Alors certains avancent simplement l'idée que la combinaison vaut mieux que l'héritage pour simplifier la réflexion de chacun.
Retour à la question principale : pourquoi Google l'implémente-t-il de cette façon ? D'un point de vue commercial, le cycle de vie d'une activité se déroulera en plusieurs étapes. Le cycle de vie complet d'un objet est implémenté par Android. Cependant, il est très raisonnable d'exposer plusieurs points clés à travers des modèles. celui qui pose la question aurait une telle idée.
巴扎黑2017-04-17 18:02:20
C’est la compréhension profonde des étrangers des frais généraux du programme. Il a pénétré profondément dans la moelle osseuse.
巴扎黑2017-04-17 18:02:20
J'ai toujours utilisé la deuxième façon d'écrire. Quand j'ai commencé à apprendre Android, j'ai utilisé la troisième façon, mais si l'auditeur a beaucoup de contenu, cela n'a pas l'air très bien
怪我咯2017-04-17 18:02:20
Je n'écris des classes anonymes que lorsqu'il y a très peu d'écouteurs, et j'implémente généralement des interfaces si le code de l'événement click est volumineux, j'écris une méthode distincte et je l'exécute dans onClick. Je pense que cette logique de code sera plus claire et plus soignée.
伊谢尔伦2017-04-17 18:02:20
Traitement abstrait des événements dans un processus d'entrée, puis résumé-le dans une interface commune. Il s’agit d’un concept de classe, non spécifique aux entreprises.
La façon dont vous écrivez plus tard est évidemment spécifique à la notion d'objets.
Je suis plus habitué à écrire comme ça. Quoi qu'il en soit, c'est une affaire spécifique et un objet spécifique, et il n'est pas nécessaire de le rendre général
ringa_lee2017-04-17 18:02:20
Pour les objets à usage unique, utilisez-les de manière anonyme !
天蓬老师2017-04-17 18:02:20
C'est juste que la classe interne contiendra des instances de la classe externe, ce qui peut facilement provoquer des fuites de mémoire
Donc en termes de performances, la première façon d'écrire est meilleure que la deuxième façon d'écrire, et la deuxième façon d'écrire vaut mieux que la troisième façon d'écrire