C# 从基类创建继承类
当我做这样的事情时C# 从基类创建继承类,c#,design-patterns,inheritance,decorator,C#,Design Patterns,Inheritance,Decorator,当我做这样的事情时 public class Car { private string make; private string model; public Car(string make, string model) { this.make = make; this.model = model; } public virtual void Display() { Console.Wri
public class Car
{
private string make;
private string model;
public Car(string make, string model)
{
this.make = make;
this.model = model;
}
public virtual void Display()
{
Console.WriteLine("Make: {0}", make);
Console.WriteLine("Model: {0}", model);
}
public string Make
{
get{return make;}
set{make = value;}
}
public string Model
{
get{return model;}
set{model = value;}
}
}
public class SuperCar:Car
{
private Car car;
private int horsePower;
public SuperCar(Car car)
{
this.car = car;
}
public int HorsePower
{
get{return horsePower;}
set{horsepower = value;}
}
public override void Display()
{
base.Display();
Console.WriteLine("I am a super car");
}
我只得到“我是一辆超级跑车”,但没有得到基类的属性。我应该在超级卡构造函数中显式分配基类的属性吗?事实上,我正在尝试Decorator模式,我希望一个类向基类添加行为 将私有属性更改为受保护的属性,除创建私有属性的类外,任何人都无法访问私有属性,而继承的类可以访问受保护的变量。或者:
Car myCar = new Car("Porsche", "911");
SuperCar mySupcar = new SuperCar(myCar);
mySupcar.Display();
通过这种方式,您可以从car继承任何类,并从提供的对象填充car内容。继承的对象不需要知道要设置什么。它们只是将当前的Car对象传递到基类上,基类就完成了这项工作。是的,要使其按您的需要工作,您需要设置基类构造函数,如下所示:
public class Car
{
public Car(string make, string model)
{
this.make = make;
this.model = model;
}
public Car (Car car):this(car.Make, Car.Model){}
}
public class SuperCar : Car
{
SuperCar(Car car): base(car){}
}
看看你的代码,我不确定它是如何编译的。您的构造函数是错误的,因为基本构造函数不知道如何运行接受car类型的构造函数。看起来您正在尝试实现decorator模式,但尚未正确实现。实际上,您应该拥有一个
ICar
接口,该接口在SuperCar
中实现并从Display()
调用car.Display()
您还必须在Super car上实现Make和Model,并使它们返回car.Make和car.Model以正确实现装饰模式
public SuperCar(Car car):base(car.make,car.model)
{
this.car = car;
}
您还没有完全实现 您需要一个抽象基类来容纳装饰过的汽车
public interface ICar
{
string Make {get; set;}
string Model {get; set;}
void Display();
}
public class Car :ICar
{
private string make;
private string model;
public Car(string make, string model)
{
this.make = make;
this.model = model;
}
public virtual void Display()
{
Console.WriteLine("Make: {0}", make);
Console.WriteLine("Model: {0}", model);
}
public string Make
{
get{return make;}
set{make = value;}
}
public string Model
{
get{return model;}
set{model = value;}
}
}
public class SuperCar:ICar
{
private ICar car;
private int horsePower;
public SuperCar(ICar car)
{
this.car = car;
}
public string Make
{
get{return car.Make;}
set{car.Make = value;}
}
public string Model
{
get{return car.Model;}
set{car.Model = value;}
}
public int HorsePower
{
get{return horsePower;}
set{horsepower = value;}
}
public override void Display()
{
car.Display();
Console.WriteLine("I am a super car");
}
我可能会来晚一点,但万一有人发现这很有用: 你可以使用反射。它需要比您建议的代码多一点的代码,但我认为它仍然提供了您正在搜索的简洁性
public abstract class CarDecorator
{
protected Car DecoratedCar { get; private set; }
protected CarDecorator(Car decoratedCar)
{
DecoratedCar = decoratedCar;
}
}
public class SuperCar : CarDecorator
{
public SuperCar(Car car)
: base(car)
{
}
public int HorsePower
{
get { return horsePower; }
set { horsepower = value; }
}
public override void Display()
{
DecoratedCar.Display()
Console.WriteLine("Plus I'm a super car.");
}
}
我从您的示例中明确地写了这篇文章,以清楚地说明这个概念,但我认为最好将其作为一个通用方法,可以在您的解决方案的所有类似实例中使用
希望这能有所帮助。基于@JoshWheelock的回答,我写了这个方法,我把它放在我的Xamarin项目的共享文件中 它克隆类,所以你可以用它来复制一个基类。如果是女继承人,你可以调整T参数
public SuperCar(Car car)
{
var props = typeof(Car).GetProperties().Where(p => !p.GetIndexParameters().Any());
foreach (var prop in props)
{
if (prop.CanWrite)
prop.SetValue(this, prop.GetValue(car));
}
// Set SuperCarcentric properties
// .
// .
// .
}
/。。。
#如果WINDOWS\u UWP
运用系统反思;
#恩迪夫
//...
公共空克隆蛋白(T src,T dest)
{
#如果WINDOWS\u UWP
var props=typeof(T).GetTypeInfo().DeclaredProperties.Where(p=>!p.GetIndexParameters().Any());
#否则
var props=typeof(T).GetProperties().Where(p=>!p.GetIndexParameters().Any());
#恩迪夫
foreach(道具中的var道具)
{
if(prop.SetMethod!=null)
属性设置值(dest,属性获取值(src));
}
}
尚未在Android和iOS上测试,关于Android,我的模拟器一周后就停止正常工作了…这是否意味着我必须从我用来创建超级跑车对象的汽车对象属性中显式分配受保护的变量?超级跑车要成为真正的装饰者,将Car的所有方法委派给您的包装车。在这里,Decorator是否是正确的模式是值得怀疑的,特别是在处理具体类时。假设您将Car重命名为Container,将SuperCar重命名为Box。您的意思是“一个盒子是一种容器(因为它继承自容器),而每个盒子都包含一个容器(因为它在构造函数中接受一个容器并将其保存在字段中)”。这就是你想要的模型吗?为什么一个盒子应该包含一个容器?为什么一辆超级跑车既包含一辆车又是一种车?我接受了Kevin的答案,因为在我的例子中,我没有接口,我想向现有的类添加额外的行为。不过,我很感谢您对decorator模式的充分解释。您是否想使用decorator模式是个问题。真的,听起来你不想要装饰图案,因为你只是想扩展汽车(这就是继承的目的),而不是包装它并改变它的工作方式,在这种情况下,凯文的是正确的解决方案。但是我可以给汽车对象指定一个超级汽车对象吗,例如,将超级跑车添加到列表中?不,您将需要一个CarDecorators列表。
//...
#if WINDOWS_UWP
using System.Reflection;
#endif
//...
public void CloneIn<T>(T src, T dest)
{
#if WINDOWS_UWP
var props = typeof(T).GetTypeInfo().DeclaredProperties.Where(p => !p.GetIndexParameters().Any());
#else
var props = typeof(T).GetProperties().Where(p => !p.GetIndexParameters().Any());
#endif
foreach (var prop in props)
{
if(prop.SetMethod!=null)
prop.SetValue(dest, prop.GetValue(src));
}
}