2013-03-14 31 views
0

我在找到本问题的解决方案时发现了此网站,我想知道是否有人可以帮助我尝试解决我的困境。无法在C#和XNA中正确初始化父类的子代

我正在使用XNA和C#创建一些用户可以从随机选择的零件组装汽车的东西。该车不一定有4个车轮和挡风玻璃。它只需要由用户选择的至少7个部分组成。我创建了一个名为“Car”的类,它将创建用户选择的所有部件的7个实例。这些部件属于“CarPart”类。我还创建了两个名为“车轮”和“挡风玻璃”的独立的“CarPart”子类。我打算在后面扩展这些部分,例如添加“Door”和“Trunk”等。

所以我在做的是Car类,我声明了7个类型为“CarPart”的对象,然后声明它们为new挡风玻璃()。或新的Wheel()。

但后来当我尝试访问挡风玻璃或车轮类的初始化函数,它只允许我来访问父“CarPart”类的初始化函数。

我想以正确的方式做到这一点,还是应该找到解决问题的另一种方法?

我也尝试使用虚拟和改写,试图超载的功能,但我似乎无法获取正常工作或者,它只是说,“找不到合适的方法超载”。

我已经包含了我的类的代码。

任何帮助都将是惊人的,我已经坚持了几天,我的项目,而不让用户能够按照自己的意愿没有这个组装汽车的功能我无法继续前进。

我发现了一些类似于我想要在此链接中执行的操作,但似乎无法使其工作。 http://csharp-station.com/Tutorial/CSharp/Lesson09

我敢肯定我在做一些我看不见的东西,因为我一直在盯着同样的问题太久。

车类:

namespace TestGame4 
{ 
    class Car 
    { 
     //Car consists of 7 CarParts chosen by the user// 
     //e.g.: 

     CarPart Part1, Part2, Part3, Part4, Part5, Part6, Part7; 

     public void Initialize(CarPart part1, CarPart part2, CarPart part3, CarPart part4, CarPart part5, CarPart part6, CarPart part7) 
     { 
      Part1 = part1; 
      Part2 = part2; 
      Part3 = part3; 
      Part4 = part4; 
      Part5 = part5; 
      Part6 = part6; 
      Part7 = part7;  

      ***//This is the part that doesn't work how I want it to. I want it to initialize 
      //as a Windshield class, but it's only initializing as a CarPart class//*** 
      part1.Initialize(

     } 
    } 
} 

CarPart class: 

namespace TestGame4 
{ 
    public class CarPart 
    { 
     public void Initialize(string assetName, Vector2 Position) 
     { 

     } 
    } 
} 

挡风玻璃类:

namespace TestGame4 
{ 
    public class Windshield : CarPart 
    { 
     public void Initialize(Vector2 Position) 
     { 

     } 
    } 
} 

轮类:

namespace TestGame4 
{ 
    public class Wheel : CarPart 
    { 
     public void Initialize(Vector2 Position) 
     { 

     } 
    } 
} 

我的主要Game1类中,我初始化汽车类,并尝试将其设置以挡风玻璃和车轮类作为参数:

namespace TestGame4 
{ 
    /// <summary> 
    /// This is the main type for your game 
    /// </summary> 
    public class Game1 : Microsoft.Xna.Framework.Game 
    { 
     GraphicsDeviceManager graphics; 
     SpriteBatch spriteBatch; 
     Car myCar; 

     public Game1() 
     { 
      graphics = new GraphicsDeviceManager(this); 
      Content.RootDirectory = "Content"; 
     } 

     /// <summary> 
     /// Allows the game to perform any initialization it needs to before starting to run. 
     /// This is where it can query for any required services and load any non-graphic 
     /// related content. Calling base.Initialize will enumerate through any components 
     /// and initialize them as well. 
     /// </summary> 
     protected override void Initialize() 
     { 
      // TODO: Add your initialization logic here 

      myCar = new Car(); 
      myCar.Initialize(new Windshield(), new Wheel(), new Windshield(), new Wheel(), new Windshield(), new Wheel(), new Windshield());   

      base.Initialize(); 
     } 

     /// <summary> 
     /// LoadContent will be called once per game and is the place to load 
     /// all of your content. 
     /// </summary> 
     protected override void LoadContent() 
     { 
      // Create a new SpriteBatch, which can be used to draw textures. 
      spriteBatch = new SpriteBatch(GraphicsDevice); 

      // TODO: use this.Content to load your game content here 
     } 

     /// <summary> 
     /// UnloadContent will be called once per game and is the place to unload 
     /// all content. 
     /// </summary> 
     protected override void UnloadContent() 
     { 
      // TODO: Unload any non ContentManager content here 
     } 

     /// <summary> 
     /// Allows the game to run logic such as updating the world, 
     /// checking for collisions, gathering input, and playing audio. 
     /// </summary> 
     /// <param name="gameTime">Provides a snapshot of timing values.</param> 
     protected override void Update(GameTime gameTime) 
     { 
      // Allows the game to exit 
      if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) 
       this.Exit(); 

      // TODO: Add your update logic here 

      base.Update(gameTime); 
     } 

     /// <summary> 
     /// This is called when the game should draw itself. 
     /// </summary> 
     /// <param name="gameTime">Provides a snapshot of timing values.</param> 
     protected override void Draw(GameTime gameTime) 
     { 
      GraphicsDevice.Clear(Color.CornflowerBlue); 

      // TODO: Add your drawing code here 

      base.Draw(gameTime); 
     } 
    } 
} 

我将是任何帮助我得到非常感谢! 在此先感谢!

回答

1

您的WindshieldWheel都是CarPart的后代。对于Car类,他们只是CarPart(定义),所以Car不知道他们中是否是WheelWindshield。至少在编译时不是。

要解决此问题,您需要向这些类添加接口。或者在CarPart中增加一个更简单的抽象函数。

abstract class CarPart 
{ 
    public abstract void Initialize(Vector2 position); 
    public void Initialize(string assetName, Vector2 position) 
    { 
    } 
} 

两个子类将需要重写此功能后,否则会过于抽象(抽象类不能用于创建对象)。

接口非常简单:接口是您从类中需要的行为。例如

interface IInitializable 
{ 
    void Initialize (Vector2 position); 
} 
class WindShield: IIinitializable 
{ 
    void Initialize (Vector2 position) 
    { 
     ... 
    } 
} 

然后你就可以在CarPart写:

IInitializable [] parts = new IInitializable [7]; 
parts[0] = new WindShield(); 
... 
parts[6] = new Wheel(); 

parts[3].Initialize(new Vector2(0, 0)); 

因此,所有这些部件符合接口IInitializable,你可以调用常用的方法Initialize (Vector2)。当不同的无关类实现相同的行为时,接口是最有用的,如IQueryableIDisposable等。

+0

非常感谢。看起来好像这解决了我的问题!但是如果我再次遇到问题,我会再问一次。 你能解释一下我的接口吗?如果它太复杂了,我可以查看它,但很高兴与某人进行讨论。 – 2013-03-14 09:57:22

+0

我改变了我的答案并添加了一些关于接口的信息。 – Aneri 2013-03-14 10:33:00

+0

可爱!非常感谢您的时间!你的解释很棒! – 2013-03-14 11:14:21

相关问题