英文:
How to better randomize method calls in Java (without repeating similar lines)?
问题
package com.delta.generics;
import android.app.Activity;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pManager;
import android.os.Bundle;
import android.service.dreams.DreamService;
import android.util.StringBuilderPrinter;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RatingBar;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class GenericsActivity extends Activity {
public TextView nameTextView = null;
public TextView descriptionTextView = null;
public RatingBar ratingView = null;
public ImageView portraitView = null;
public Button nextButton = null;
private int currentSelection = 0;
AdoptAdapter<Cat> catAdoptAdapter;
AdoptAdapter<Dog> dogAdoptAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_generics);
nameTextView = (TextView) findViewById(R.id.nameTextView);
descriptionTextView = (TextView) findViewById(R.id.descriptionTextView);
ratingView = (RatingBar) findViewById(R.id.ratingView);
portraitView = (ImageView) findViewById(R.id.portraitView);
nextButton = (Button) findViewById(R.id.nextButton);
nextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showNext();
}
});
catAdoptAdapter = new AdoptAdapter<Cat>(this, nameTextView, descriptionTextView, ratingView, portraitView);
dogAdoptAdapter = new AdoptAdapter<Dog>(this, nameTextView, descriptionTextView, ratingView, portraitView);
catAdoptAdapter.set(AdoptData.mCatList.get(0));
dogAdoptAdapter.set(AdoptData.mDogList.get(0));
}
public void showNext(){
int random = currentSelection;
int animal_random = (int) (Math.random() * 2);
while(random == currentSelection){
if (animal_random == 0) {
random = (int) (Math.random() * AdoptData.mCatList.size());
} else {
random = (int) (Math.random() * AdoptData.mDogList.size());
}
}
currentSelection = random;
if (animal_random == 0) {
Cat c = AdoptData.mCatList.get(random);
catAdoptAdapter.set(c);
} else {
Dog d = AdoptData.mDogList.get(random);
dogAdoptAdapter.set(d);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.generics, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
The revised showNext()
method has eliminated the repeated lines by checking the animal_random
value and deciding whether to work with cats or dogs accordingly. This simplifies the code and avoids unnecessary duplication.
英文:
I have this file as an example of a Pet app for Android that showcases profiles of cats or dogs (courtesy of a Udemy course). this is the base file:
package com.delta.generics;
import android.app.Activity;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pManager;
import android.os.Bundle;
import android.service.dreams.DreamService;
import android.util.StringBuilderPrinter;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RatingBar;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class GenericsActivity extends Activity {
public TextView nameTextView = null;
public TextView descriptionTextView = null;
public RatingBar ratingView = null;
public ImageView portraitView = null;
public Button nextButton = null;
private int currentSelection = 0;
// CatAdapter catAdapter;
AdoptAdapter<Cat> catAdoptAdapter;
// AdoptAdapter<Dog> dogAdoptAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_generics);
nameTextView = (TextView) findViewById(R.id.nameTextView);
descriptionTextView = (TextView) findViewById(R.id.descriptionTextView);
ratingView = (RatingBar) findViewById(R.id.ratingView);
portraitView = (ImageView) findViewById(R.id.portraitView);
nextButton = (Button) findViewById(R.id.nextButton);
nextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showNext();
}
});
// commenting this out in favour of AdoptAdapter objects
// catAdapter = new CatAdapter(this,nameTextView,descriptionTextView,ratingView,portraitView);
// catAdapter.set(AdoptData.mCatList.get(0));
catAdoptAdapter = new AdoptAdapter<Cat>(this, nameTextView, descriptionTextView, ratingView, portraitView);
// dogAdoptAdapter = new AdoptAdapter<Dog>(this, nameTextView, descriptionTextView, ratingView, portraitView);
catAdoptAdapter.set(AdoptData.mCatList.get(0));
// dogAdoptAdapter.set(AdoptData.mDogList.get(0));
// mCatList and mDogList is an object already exists in AdoptData.java
}
public void showNext(){
int random = currentSelection;
int animal_random = 0;
animal_random = (int )(Math.random() * 2;
while(random == currentSelection){
//avoid same selection twice.
random = (int )(Math.random() * AdoptData.mCatList.size());
random = (int )(Math.random() * AdoptData.mDogList.size());
}
currentSelection = random;
Cat c = AdoptData.mCatList.get(random);
// Dog d = AdoptData.mDogList.get(random);
// commenting in favour of AdoptAdapter object
// catAdapter.set(c);
catAdoptAdapter.set(c);
// dogAdoptAdapter.set(d);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.generics, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
The issue I see is that the way this is formatted, it can only either showcase Cat or Dog profiles, but not together, and I wanted to figure out a way of how to "mix" them so both Cats and Dogs shows up randomly when pressing the "Next" button. And so I figured within the context of Java and this file, I figured I can modify the showNext()
method:
public void showNext(){
int random = currentSelection;
int animal_random = 0;
animal_random = (int )(Math.random() * 2);
Log.e("animal_random", String.valueOf(animal_random));
switch(animal_random){
case 0:
while(random == currentSelection){
//avoid same selection twice.
random = (int )(Math.random() * AdoptData.mCatList.size());
}
currentSelection = random;
Cat c = AdoptData.mCatList.get(random);
catAdoptAdapter.set(c);
break;
case 1:
while(random == currentSelection){
//avoid same selection twice.
random = (int )(Math.random() * AdoptData.mDogList.size());
}
currentSelection = random;
Dog d = AdoptData.mDogList.get(random);
dogAdoptAdapter.set(d);
break;
}
}
But I feel like there are way too many "repeated lines" here. If this were in Python I would probably utilize the getAttribute()
method to determine which method to use in the object based on a string match. However when I tried to use the supposed Java equivalent getMethod()
i keep getting a java.lang.NoSuchMethodException
error when i try to use it.
Is there a better way to go about this in Java...? Or would it require a complete restructure for this specific example?
答案1
得分: 1
一旦你从以下两个替代方案中选择了任何一个,只需更新你的代码的其余部分,你可能会在整个代码中看到较少的重复,因为动物们将在某个共同点上有交集。
接口方式
创建一个名为 Animal
的接口,使你能够访问给定情况下动物的共同特征,然后在你的 Dog
和 Cat
类中实现该接口。你的问题中的代码可能主要涉及 Animal
,除非你需要以某种方式明确区分 Dog
和 Cat
。
这种方法的一个好处是,虽然接口将强制执行一个契约,但它也为你提供了余地,例如,如果你希望 Dog
类能够包含 Cat
不应该包含的内容。也许它已经实现了?
枚举方式
将你的 Dog
和 Cat
类合并为一个名为 Animal
的类,其中包含一个名为 type
的 enum
字段或类似的内容。减少了类的数量(万岁?),但要注意的是,狗、猫以及你将来添加的任何其他动物都必须适应相同的数据结构。根据动物的实际类型有多少重要性和意义,这可能是个好主意,也可能不是个好主意。
英文:
Once you've picked any of the two alternatives below, just update the rest of your code and you'll probably see less duplication across the board since the animals will have a common ground somewhere.
The interface way
Create an Animal
interface that gives you access to the common things for animals in your given case, and then implement the interface in both your Dog
and your Cat
class. Your code in question will probably mostly be talking about Animal
s instead, unless you explictly need to differentiate between a Dog
or a Cat
in some way.
One of the neat things about this approach is that while the interface will enforce a contract, it also gives you the wiggle room for if you example want the Dog
class to be able to contain stuff that the Cat
shouldn't. Maybe it already does?
The enum way
Consolidate your Dog
and Cat
classes into a single Animal
class that carries an enum
field called type
or something like that. Less classes (hurray?), but with the caveat that the dogs, cats and whatever future animals you add kinda have to fit into the same data structure. Depending on how much weight and meaning the actual type of animal actually has, this may or may not be a really bad idea.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论