[英]Abstraction and Proper Class Design
我对编程并不陌生,但是对OOP相对较新,所以我有一个设计问题。 实际上,在同一问题中我有两个问题。
为了简单起见,假设我正在设计一个FruitBasket
类。 除了FruitBasket
类,我还将设计一个Apple
类,一个Orange
类和一个Pear
类。 每当我实例化FruitBasket
类型的对象时,它将自动以has-a关系实例化这些其他类。
class Apple { //Apple implementation here }
class Orange { //Orange implementation here }
class Pear { //Pear implementation here }
class FruitBasket
{
Apple _apple;
Orange _orange;
Pear _pear;
public FruitBasket()
{
_apple = new Apple();
_orange = new Orange();
_pear = new Pear();
}
}
class Program
{
FruitBasket _fruitBasket;
static void Main()
{
_fruitBasket = new FruitBasket();
}
}
好的,这是我的问题:
FruitBasket
构造函数中实例化各种水果对象是否可以接受,还是这种不好的做法? Apple
和一个Orange
水果篮该怎么办? Pear
和Orange
? Apple
和Pear
? 等等,最好的方法是什么? 最好创建一个FruitBasket
类来声明每个可能放入篮子的水果,并传递一些参数来告诉FruitBasket
类实例化哪个水果类?
我真的不知道哪种方法最有效,或者即使我的想法还在讨论之列。
我的建议是不要为FruitBasket
创建默认构造FruitBasket
。 这样,您可以使用Object Initializer语法完全按照您的意思进行操作。 您将需要像下面那样更改FruitBasket
类:
public class FruitBasket
{
public Apple apple { get; set; }
public Orange orange { get; set; }
public Pear pear { get; set; }
}
然后,您将能够如下创建FruitBasket:
var fb1 = new FruitBasket { apple = new Apple() };
var fb2 = new FruitBasket { pear = new Pear() };
var fb3 = new FruitBasket { apple = new Apple() orange = new Orange() };
Object Initializer语法非常强大,如果您的类实际上只是一个“属性包”,那么它通常是最简单的方法。
编辑:您可能还想让您的水果继承自Fruit
基类。 如果这样做,则可以结合使用对象初始化语法和集合初始化语法。 如果将FruitBasket
类更改为以下内容:
public class FruitBasket
{
public List<Fruit> fruit { get; set; }
}
您可以按以下方式初始化FruitBasket
:
var fb3 = new FruitBasket{ fruit = new List<Fruit> { new Apple(), new Orange() } };
var fb4 = new FruitBasket{ fruit = new List<Fruit> { new Orange() } };
var fb5 = new FruitBasket{ fruit = new List<Fruit> { new Apple(), new Orange(), new Pear() } };
水果篮必须有该水果,否则有时可能是空的? 你可以重复任何水果吗? 如果是,则应该研究继承和泛型,在泛型中必须有一个基类Fruit,而篮子可能只是一个泛型List
abstract class Fruit
{
}
class Apple : Fruit
{
//Apple implementation here
}
class Orange : Fruit
{
//Orange implementation here
}
class Pear : Fruit
{
//Pear implementation here
}
class Program
{
static void Main()
{
List<Fruit> _fruitBasket = new List<Fruit>();
_fruitBasket.Add(new Orange());
_fruitBasket.Add(new Apple());
}
}
或者,您可以执行以下操作以使篮子尽可能多地丰富:
abstract class Fruit {}
class Apple :Fruit { //Apple implementation here }
class Orange : Fruit { //Orange implementation here }
class Pear :Fruit { //Pear implementation here }
class FruitBasket
{
public List<Fruit> Contents {get;set;}
public FruitBasket()
{
Contents = new List<Fruit>{new Apple(), new Orange(), new Pear()};
}
}
这是我将如何处理该问题的方法。 而不是在篮中使用一组预定义的水果,而是使用“水果集合”使它变得灵活。 您将无法将它们传递到构造函数中,而是通过方法添加它们。 为此,每个水果类都继承相同的接口(例如IFruit)
所以你有了
class Apple : IFruit { ... }
class Orange : IFruit { ... }
etc
好处是,您可以根据需要添加任意种类的水果,而不仅限于苹果,橙子和梨。
水果篮可能看起来像这样
public class FruitBasket {
public FruitBasket() {
_basket = new List<IFruit>();
}
public List<IFruit> Fruits {
get { return _basket; }
}
public AddFruit(IFruit fruit) {
_basket.Add(fruit);
}
private readonly List<IFruit> _basket
}
我会设计不同。
class Fruit
{
}
class Apple : Fruit
{ //Apple implementation here }
class Orange : Fruit
{ //Orange implementation here }
class Pear : Fruit
{ //Pear implementation here }
class FruitBasket
{
Ilist<Fruit> Fruits;
public FruitBasket()
{
Fruits =new List<Fruit>();
}
public AddFruit(Fruit)
{
// Add Fruit implementation here
}
public RemoveFruit(Fruit)
{
// Remove Fruit implementation here
}
}
class Program
{
FruitBasket _fruitBasket;
static void Main()
{
Fruit orange=new Orange();
_fruitBasket = new FruitBasket();
_fruitBasket.AddFruit(orange);
}
}
大概一个FruitBasket
可以容纳任何类型的水果,对吗? 这听起来像多态性和依赖反转的情况。
class FruitBasket {
readonly List<Fruit> _fruits = new List<Fruit>();
public FruitBasket(params Fruit[] fruits) {
_fruits.AddRange(fruits);
}
}
interface Fruit {}
class Apple : Fruit {}
class Orange : Fruit {}
在OOP中,通常会传递依赖项。“预先了解”什么是依赖项是更具过程性的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.