Class 如何使用OOP设计类?

Class 如何使用OOP设计类?,class,oop,Class,Oop,我现在对课程设计有问题。问题如下: 我想为水果和果汁机设计课程。水果(苹果、梨、桃)的课程已经完成。现在我想为榨汁机设计类 榨汁机的要求如下: 榨汁机榨取特定的水果(苹果、梨、桃)并榨汁。注:可能有混合果汁(如苹果和梨的味道) 2.一台榨汁机只能生产一种果汁 榨汁机有储存水果的空间,我们可以知道还有多少苹果或梨在那里。(我们假设每次一台榨汁机使用一个苹果或梨) 有谁能给我一些建议吗?我将从实施 榨汁机设计类 它将帮助您构造一个复杂对象(juice)并分离其表示,以便相同的构造过程可以创建不同的表

我现在对课程设计有问题。问题如下:

我想为水果和果汁机设计课程。水果(苹果、梨、桃)的课程已经完成。现在我想为榨汁机设计类

榨汁机的要求如下:

榨汁机榨取特定的水果(苹果、梨、桃)并榨汁。注:可能有混合果汁(如苹果和梨的味道)

2.一台榨汁机只能生产一种果汁

榨汁机有储存水果的空间,我们可以知道还有多少苹果或梨在那里。(我们假设每次一台榨汁机使用一个苹果或梨)


有谁能给我一些建议吗?

我将从实施

榨汁机设计类

它将帮助您构造一个复杂对象(juice)并分离其表示,以便相同的构造过程可以创建不同的表示(juice的种类)

将一些接口(IFruit)和基类(重量、大小等的共享代码)添加到

水果类(苹果、梨、桃)

每个榨汁机都有

ICollection<IFruit> fruits
i采集水果
这是可以管理的-
.Count()
.Add(IFruit)
.Remove(IFruit)
如果您的语言支持(如C和Java),最简单的解决方案是使榨汁机通用:

public class Juicer<T>
{
    private T[] fruits;

    public Juicer(T[] fruits)
    {
        this.fruits = fruits;
    }

    public FruitCount
    {
        get { return this.fruits.Length; }
    }

    // Other members can go here...
}
公共类榨汁机
{
私人水果;
公共榨汁机(T[]水果)
{
这个。水果=水果;
}
公众水果计数
{
获取{返回this.fruits.Length;}
}
//其他成员可以到这里来。。。
}

您可以创建一个对象作为
榨汁机
,另一个对象作为
榨汁机
,依此类推。
榨汁机只能包含
苹果
对象等。

马克的回答很好,这是一个很好的开始。。。我会扩展一点。我可能不会对水果使用数组,因为您将添加、删除等。。。使用列表或类似工具可能更容易实现。此外,莱恩说他希望在一些榨汁机中加入多种水果。。这让事情变得复杂了一点,给了我们一些决策

如果它总是最多两个水果,我可能会制作两个类似于Mark答案中的榨汁机类:

public interface IFruit
{
    string Name {get;}
}

public class Apple : IFruit
{
    public string Name { get {return "Apple";} }
}

public class Pear : IFruit
{
    public string Name { get {return "Pear";} }
}

public class Juicer<IFruit>
{
    private IList<IFruit> fruits;

    public Juicer(IList<IFruit> fruits)
    {
        this.fruits = fruits;
    }

    public int FruitCount
    {
        get { return this.fruits.Count; }
    }

    // Other members can go here...
}


public class TwoFruitJuicer<IFruit, IFruit2>
{
    private IList<IFruit> fruits;
    private IList<IFruit2> fruits2;

    public TwoFruitJuicer(IList<IFruit> fruits, IList<IFruit2> fruits2)
    {
        this.fruits = fruits;
        this.fruits2 = fruits2;
    }

    public int FruitCount
    {
        get { return this.fruits.Count + this.fruits2.Count; }
    }

    // Other members can go here...
}
公共接口IFruit
{
字符串名称{get;}
}
公共级苹果:IFruit
{
公共字符串名称{get{return“Apple”;}
}
公共级梨:IFruit
{
公共字符串名称{get{返回“Pear”;}
}
公营榨汁机
{
私家水果;
公共榨汁机(IList水果)
{
这个。水果=水果;
}
公共整数计数
{
获取{返回this.fruits.Count;}
}
//其他成员可以到这里来。。。
}
公共二级果汁机
{
私家水果;
私营机构2;
公共双水果榨汁机(IList水果,IList水果2)
{
这个。水果=水果;
this.fruits2=fruits2;
}
公共整数计数
{
获取{返回this.fruits.Count+this.fruits2.Count;}
}
//其他成员可以到这里来。。。
}
但是,假设你想要3或4台不同的榨汁机组合在一起

public class MulitJuicer
{
    private IList<Juicer<IFruit>> _juicers;

    public MulitJuicer(IList<Juicer<IFruit>> juicers)
    {
        this._juicers = juicers;    
    }

    public int FruitCount
    {
        get {

            int allFruitCount = 0;

            foreach (var j in _juicers)
            {
                allFruitCount += j.FruitCount;
            }

            return allFruitCount;
        }
    }
}
公共类多功能榨汁机
{
私人IList_榨汁机;
公共多功能榨汁机(IList榨汁机)
{
这个._榨汁机=榨汁机;
}
公共整数计数
{
得到{
int-allfructcount=0;
foreach(var j in_榨汁机)
{
AllFrootCount+=j.FrootCount;
}
返回所有水果计数;
}
}
}
然而,这可能会很难使用,列表中有很多列表用来跟踪构建等等。。。如果你只需要一个榨汁机,你可以把一堆水果倒进去呢?我们可以使用反射来验证榨汁机中是否只放入了允许的水果:

public class MultiFruitJuicer
{
    private IList<Type> _juiceTypes;
    private IList<IFruit> _fruits;

    public MultiFruitJuicer(IList<Type> juiceTypes, IList<IFruit> fruits)
    {
        _juiceTypes = juiceTypes;
        _fruits = fruits;

        if (!ValidateFruits())
        {
            //you may not want to actually throw here...
            throw new Exception("Not all proper fruit types");
        }
    }

    public bool ValidateFruits()
    {
        //there are about a million ways to do this... this is probably not the best...
        foreach(var f in _fruits)
        {
            if (!_juiceTypes.Contains(f.GetType()))
            {
                return false;
            }
        }

        return true;
    }

    public int FruitCount
    {
        get { return this._fruits.Count; }
    }
}
公共类多水果榨汁机
{
私人IList_JuiceType;
私人水果;
公共多水果榨汁机(IList JuiceType、IList水果)
{
_juiceTypes=juiceTypes;
_水果=水果;
如果(!ValidateFruits())
{
//你可能不想在这里扔东西。。。
抛出新异常(“并非所有正确的水果类型”);
}
}
公共bool ValidateFruits()
{
//有大约一百万种方法可以做到这一点…这可能不是最好的。。。
foreach(水果中的f值)
{
如果(!\u juiceTypes.Contains(f.GetType()))
{
返回false;
}
}
返回true;
}
公共整数计数
{
获取{返回此。\u fruits.Count;}
}
}

有两件事让我对这个答案投了反对票:a)2015年的一个无基础的单例推荐b)没有迹象表明在公共接口和/或基类下强制执行结果是合理的。这有一个缺点,即在不知道此代码的情况下关闭添加类型的榨汁机访问。如果有的话,我希望有一个对通用榨汁机的类型擦除访问,这是另一个答案建议的。@bartek
Fruit
接口将确保如果添加了新的水果类型,其余的代码仍然可以使用它-
榨汁机
。此外,它还可以让你收集水果。基类将有助于避免重复所有fruit字段、属性和方法的公共类。但这也意味着,如果不编写复杂的适配器,您将无法适应任何不是从Fruir继承或实现fruit接口的类,哪些类不会继承或实现水果功能?它们是水果吗?那么呢?在你的代码之外可能有一些你不知道的类型,它们可能满足于作为一个水果。您不能轻松地为外部类编写接口实现,这一事实使得接口的实用性大大降低。如果我们谈论的是一种语言