我正在尝试用Java建模太阳能系统,并且需要存储不同随机数量的对象类型并以某种方式保留它们的顺序。我目前正在使用以下类结构:
class PlanetarySystem - currently has a list of each object type (below)
class planetaryBody
class star extends planetaryBody
class planet extends planetaryBody
class belt extends planetaryBody
class disk extends planetaryBody
例如,假设我想通过系统循环显示PlaneitaryBody对象的详细信息。 Star的统计数据可能与Planet不同,依此类推。这是一个简单的例子。
public class PlanetaryBody
{
private String name;
public PlanetaryBody()
{
this.name = "Generic Name";
}
public String getName()
{
return this.name;
}
}
public class Star extends PlanetaryBody
{
private int temperature;
public Star()
{
this.temperature = 12345;
}
public String getTemp()
{
return this.getTemp();
}
}
现在,如果我稍后创建类似
的内容List<planetaryBody> system = new List<planetaryBody>();
//then put some stars, planets, disks, etc in.
system.get(x).getName() //will work
system.get(x).getTemp() //will not work because type is planetaryBody
后来我想循环浏览列表然后让我们说出一切的名称,恒星的温度,皮带的大小,行星的颜色等等。我认为我不会拉出子类的特定函数。这是我试图解决的问题。
我可以创建一些东西,允许我按顺序存储对象,保留它们的内容,然后再对该类进行特定的操作吗?
我正在考虑尝试使用地图树,但我想我必须将它与planetBody类型一起使用。当我试图将物体拉出来并将它们作为行星体出来时,这会产生问题。我已经读过,做if语句来弄清楚它们是什么类不是最好的OOP练习,老实说我甚至都不知道这是否会按预期工作。
我是新人,学习,所以举例,并进一步阅读。
编辑:更多说明。
答案 0 :(得分:1)
您的问题有很多解决方案,每个解决方案各有利弊,也有很多意见。我只是想提出一个老技巧,这里结合现代public class NavigationBarManager extends RecyclerView.Adapter<NavigationBarManager.FilterItemHolder> implements OnItemSelectedListener, AnimatorListener{//, Observer {
private static final String TAG = "NavigationBarManager";
private RecyclerView mRecyclerView ;
private int mSelectedItem = 0;
private NotificationHandler mAnimNtfHandler;
public static final int DIRECTION_LEFT = -1;
public static final int DIRECTION_RIGHT = 1;
Context mContext;
FilterItemHolder mFilterItemHolder;
private ArrayList<String> mFilterStringList;
private ArrayList<Drawable> mFilterDrawableList;
private ArrayList<Integer> mCursorIdxList;
private ArrayList<Integer> mFilterIdList;
private HtvChannelListUtil mListUtil;
private ITvSettingsManager mSettings;
private RecyclerView.SmoothScroller smoothScroller;
private LinearLayoutManager mRecyclerViewMgr = null;
public NavigationBarManager(Context context)
{
mContext = context;
mAnimNtfHandler = NotificationHandler.getInstance();
mFilterStringList = new ArrayList<String>();
mFilterDrawableList = new ArrayList<Drawable>();
mFilterIdList = new ArrayList<Integer>();
mCursorIdxList = new ArrayList<Integer>();
mListUtil = HtvChannelListUtil.getInstance();
mSettings = ITvSettingsManager.Instance.getInterface();
mCacheManager = HtvChannelCacheManager.getInstance();
mFillDataIntoNavigationBar();
mNtfHandler = NotificationHandler.getInstance();
}
public void setLayoutManager(LinearLayoutManager pRecyclerViewMgr)
{
mRecyclerViewMgr = pRecyclerViewMgr;
}
public class FilterItemHolder extends RecyclerView.ViewHolder
{
ImageView imageView;
//ImageView mBgView;
public FilterItemHolder(View itemView)
{
super(itemView);
// get the reference of item view's
imageView=(ImageView) itemView.findViewById(R.id.imageview);
//mBgView = (ImageView) itemView.findViewById(R.id.bgView);
}
}
@Override
public FilterItemHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
Log.e(TAG,"onCreateViewHolder viewType" +viewType);
View lViewHolder = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
FilterItemHolder lHolder = new FilterItemHolder(lViewHolder);
mFilterItemHolder = lHolder;
return lHolder;
}
@Override
public void onBindViewHolder(FilterItemHolder holder, final int position)
{
Log.e(TAG,"onBindViewHolder position=" +position);
Log.e(TAG,"onBindViewHolder getAdapterPosition=" +holder.getAdapterPosition());
Log.e(TAG,"mSelectedItem=" +mSelectedItem);
holder.imageView.setImageDrawable(mFilterDrawableList.get(position));
if(position == mSelectedItem)
{
holder.imageView.requestFocus();
holder.imageView.setSelected(true);
Log.e(TAG,"requesting focus=");
//holder.mBgView.setBackgroundResource(R.drawable.button_box_hil);
}
else
{
holder.imageView.setSelected(false);
//holder.mBgView.setBackgroundResource(0);
}
}
@Override
public void onAttachedToRecyclerView(final RecyclerView recyclerView)
{
super.onAttachedToRecyclerView(recyclerView);
mRecyclerView = recyclerView;
}
@Override
public void onItemSelected(AdapterView<?> pParent, View pView, int pPosition, long pId)
{
Log.d(TAG,"onItemSelected " + pPosition);
}
@Override
public int getItemCount()
{
return mFilterDrawableList.size();
}
@Override
public void onNothingSelected(AdapterView<?> arg0)
{
Log.e(TAG,"onNothingSelected");
}
@Override
public void onAnimationCancel(Animator pAnimator)
{
}
@Override
public void onAnimationEnd(Animator pAnimator)
{
}
@Override
public void onAnimationRepeat(Animator pAnimator)
{
}
@Override
public void onAnimationStart(Animator pAnimator)
{
}
public void moveFocus(int pDirection)
{
int lNextSelect = mSelectedItem + pDirection;
if (lNextSelect >= 0 && lNextSelect < getItemCount())
{
//notifyItemChanged(mSelectedItem);
mSelectedItem = lNextSelect;
//notifyItemChanged(mSelectedItem);
mRecyclerView.smoothScrollToPosition(mSelectedItem);
if(mRecyclerView.getChildAt(mSelectedItem) != null)
{
//mRecyclerView.getChildAt(mSelectedItem).requestFocus();
}
}
else
{
return;
}
setNavigatorText();
setCurrentSelection(mSelectedItem);
int lSelectedList = mCursorIdxList.get(mSelectedItem);
mCacheManager.setCurrentListIdx(lSelectedList);
mListUtil.selectList(lSelectedList);
mNtfHandler.notifyAllObservers(EventID.CH_LIST_REFRESH,null);
}
public void refresh()
{
mRecyclerView.smoothScrollToPosition(mSelectedItem);
int lCurrentList = mCacheManager.getCurrentListIdx();
int lNewSelection = mCursorIdxList.indexOf((Integer)lCurrentList);
Log.d(TAG,"refresh: old selection - "+ mSelectedItem + "new selection - " + lNewSelection);
if(mSelectedItem != lNewSelection)
{
//notifyItemChanged(mSelectedItem);
mSelectedItem = lNewSelection;
//notifyItemChanged(mSelectedItem);
if(mRecyclerView.getChildAt(mSelectedItem) != null)
{
mRecyclerView.getChildAt(mSelectedItem).requestFocus();
}
setNavigatorText();
setCurrentSelection(mSelectedItem);
}
}
}
。超类:
Optional
示例子类:
public abstract class PlanetaryBody {
/**
* @return If this PlanetaryBody is a Star, then an Optional containing this as a Star.
* Otherwise an empty Optional.
*/
public Optional<Star> asStar() {
return Optional.empty();
}
public Optional<Planet> asPlanet() {
return Optional.empty();
}
// Similar methods for other subclasses
}
以上允许我们使用这样的类:
public class Star extends PlanetaryBody {
public void shineBrightly() {
// ...
}
@Override
public Optional<Star> asStar() {
return Optional.of(this);
}
}
优点:
PlanetaryBody body = // ...
body.asStar().ifPresent(s -> {
// body is a star
s.shineBrightly();
});
或其他皱眉结构。缺点:
编辑:我正在使用Java 8中引入的instanceof
类。主要(仅?)的目的是从方法中返回null的安全值。当一个方法可能返回某些内容或者什么都没有时 - 例如Optional
可能会发生 - 旧的方法是让它返回一个可能是asStar
的引用。当调用者不知道返回值可能是null
或者忘记检查时,这会产生NullPointerException
s。经常发生。您可能会争辩说,在这种情况下,这不是一个很大的风险,因此我们可以将null
作为this
或Star
返回。
使用null
方法永远不需要(也绝不能)返回Optional
。相反,它会返回一个null
,其中包含或不包含值。我通常使用Optional
从方法获得的方法是通过其Optional
方法,如上所示。我将lambda(或方法引用)传递给它,并且只有存在值时才执行内部代码。因此,在我的代码中isPresent
是对s
内Star
的引用,并且保证为非空(否则代码将不会被执行)。
Java 9引入了变体Optional
,它还将在ifPresentOrElse
为空的情况下执行代码块。
您当然可以在互联网上阅读有关Optional
的更多信息。我变得非常喜欢它。如果您可以在谈话的背景下阅读,我推荐下面链接中的幻灯片 - 否则,YouTube上也可以提供该演讲。需要注意的一点是:如果您在某个地方读到应该使用方法Optional
和Optional.isPresent
,请不要相信,您很少应该这样做(请注意Optional.get
与s之间的区别isPresent
使用f,两种方法都存在,请像我一样使用后者。
不使用ifPresent
的变体(未经测试)。在超类中:
Optional
在具体的子类中:
public Star asStar() {
return null;
}
使用方法:
public Star asStar() {
return this;
}
链接: Slide deck Optional: The Mother of All Bikesheds by Stuart Marks, Oracle