I'm starting to learn how to create C# and using Interface and Class.
Can someone teach me how to separate my Class and my Interface and still maintain their connection from one another?
Reason: If I'll be updating my code, I'll know where to add them and it will be less code in my screen.
namespace Car
{
class MainClass
{
//My Interface
interface ICar
{
int gas { get; set; }
//void refuel();
int getGasLeft();
}
//My Class
class Car : ICar
{
public int gas { get; set; }
public Car(string _name)
{
name = _name;
dist = 0;
gas = 40;
}
public void refuel(int lit)
{
gas += lit;
}
public int getGasLeft()
{
return gas;
}
}
//Main
public static void Main(string[] args)
{
Car toyota = new Car();
toyota.drive(100);
toyota.refuel(5);
Console.WriteLine("Name: " + toyota.name +
"\nGas Left: " + toyota.getGasLeft());
Console.ReadLine();
}
}
}
In C#, a namespace is the way to connect files from different places.
For example, you can make a folder Interfaces and put your ICar there. I will show you an example from my project.
My folder structure looks like this:
In my ViewModel.cs I use an object named FakeData. As you can see below, class FakeData is in the TaskManager.Models namespace.
Now, we are going to our project and we are looking at the Models folder.
In C#, when you create a folder and a class in it, you will get a namespace based on your folder name. Of course, you can change it. You can edit the namespace how you want to.
In your case, you can simply make a folder called Interfaces. Right click, then select New Class, and give it a name, for example, Icar.cs. Paste your code there. Your default namespace will be ProjectName.Interfaces. Make your interface public. Then, you can call your interface by adding using ProjectName.Interfaces in the top of your main class. Then you can do Main : ICar without any errors.
Same idea with the Car class. You can make a folder named Models and a class in it that called Cars.cs. It will have the namespace ProjectName.Models. If you want to use your interface that is in Interfaces folder, you need to add a namespace to your Car.cs class. In your case, it will look like using ProjectName.Interfaces. Then, you can call the interface in Car.cs without any error.
Feel free to ask me any questions about this. I will try to help you.
You need to learn about public, private, protected, namespaces, and so on.
On your case, create a new file called ICar.cs in the same folder and declare it as public interface in the same namespace.
Related
There is something I do not understand about open-close principle. Let's say that you have done this code:
public abstract class Player
{
public string Name { get; set; }
public int Level { get; set; }
}
public sealed class Fighter : Player { /* ... */ }
public sealed class Warrior : Player { /* ... */ }
This code works perfectly, you've done a first release, eveyrthing is OK.
Now you want to add some features, like a player can equip a ring. Open-close principle says open to extension, close to modification. How could I implement the fact that my players can have rings if I shouldn't modify these class?
You can modify class Player by adding new methods and fields. It is open to extension. But if you already have some methods like Jump or Fight and you want to modify them - that is breaking the principle.
Imagine, your class Fighter has method Fight() and it uses only bare hands:
public Fighter() : Player
{
...
public virtual void Fight()
{
//use bare hands
}
}
If you want Fighter to fight with a stick (for example) you should not modify initial method Fight() but add another class like FighterWithStick : Fighter and override method Fight() there:
public FighterWithStick() : Fighter
{
...
public override void Fight()
{
//use stick
}
}
First think why this kind of rule might be useful. Closed to modification, open to extension. This makes sense for libraries or code that must be backwards compatible. Think of this example:
I've written "BestLibrary" library which exposes interface:
namespace BestLibrary
{
public interface GoodStuff
{
Goodies GiveMeGoodStuff();
}
}
But in the next release I want to decide what Goodies to give based on a parameter, so I change the interface to:
namespace BestLibrary
{
public interface GoodStuff
{
Goodies GiveMeGoodStuff(GoodiesType type);
}
}
public enum GoodiesType { All, Type1, Type2 }
Now everyone who uses my library has to fix their code, because their projects will stop building. This brakes Open/Closed principle. Instead I should make another method, like this:
namespace BestLibrary
{
public interface GoodStuff
{
Goodies GiveMeGoodStuff();
Goodies GiveMeGoodStuff(GoodiesType type);
}
}
Here I didn't modify anything. Old code still works. Someone wants random Goodies? They can still get it. I extended GoodStuff interface with additional method. This way everything compiles and people can use new functionality.
If you work on a project that is not a library or api, then I don't see any reason to follow this principle. Requirements change and code should follow.
I've defined a simple interface:
public interface Categorizable {
string Category { get; set; }
}
Elsewhere, I try to use it in a function:
public void Add(Categorizable item)
{
string cat = item.Category;
}
However, Visual Studio tells me "Categorizable does not contain a definition for Category".
How do I fix this so that Category can be used as an accessible property?
Interfaces should really have an I in front of them i. ICategorizable, its very common and a standard for C#.
Check you haven't declared a class with the same name.
Check you haven't declared your interface somewhere else.
If this is coming from a class library, check you are actually using the correct version, and its builds with your project.
Other than this, there isn't much else that can go wrong. This is how interfaces work (without deviation).
My goal is something along these lines:
// Defines members, for the "change-log" of the API,
// if the interface has changed, the API has a new major version.
// For "automatically generating changelogs" (for major versions) of the API
interface IApp
{
static string Name { get; set; }
}
// Internal class, not for usage outside of the dll
internal static class AppConfig
{
internal static bool IsPublished;
}
// Public available members from the API
public static class App : AppConfig, IApp
{
public static string Name { get; set; }
}
Now, there are a few wrongs in the structure above, based on C# language:
The interface cannot have static members
The class App is static, so it cannot inherit a static class
The AppConfig is static, so it cannot be inherited from
The class App is static, so it cannot have an interface
My current "solution":
public static partial class App
{
internal static bool IsPublished;
}
public static partial class App
{
public static string Name { get; set; }
}
Which I wanted to add contracts/interfaces to... So, I would maybe end up with something along these lines, "wrapping" APP:
public static class App
{
private static _App app;
static App()
{
app = new _App();
}
public static string Name { get { return app.Name; } }
}
internal interface _IApp
{
string Name { get; set; }
}
internal class _App : _AppConfig, _IApp
{
public string Name { get; set; }
}
internal class _AppConfig
{
internal static bool IsPublished;
}
This is long, tedious and boring. Three places to update insert a new member: Interface, _App-class (implementation) and in the static App-class (for API-users).
I want to achieve two things: A contract, interface, which defines all major changes from one version to another (read interfaces, print to change-log).
Making things that shall not be used for users of the API private (internal...).
The question? Anyone done something similar before, how did you solve it? Or talk me into forgetting the idea of a changelog based on interfaces... Because interfaces requires non-static objects, while I want static objects (at least on this particular object, it is static!).
PS: Atm. I read all public objects/members of the API to a log, which is now the "changelog". But starting on a new API, wanted to do something... different. :)
Edit: Note; I care about how the object looks on the "other side", it is an important thing. User of the API, to call App-members, shall be as simple as this (straight forward):
System.Windows.App.Name;
Which means the "outer class" (or however you want to look at it), is a static object.
Last note: I have several (12-15) objects of this "type", so I wanted a elegant structure, for all objects, all named similarly, so if you get to know one object, you know them all. Meaning: if one object has an interface, all others has one too. If one object is named "AppConfig", you can bet your life on that the other object also has a class named "OtherConfig". :)
It sounds like you're trying to have different "flavors" of the same class. Each one shares some common functionality? If so, I would use an abstract class as the base instead of an interface. Then, derive the other classes from that one. Unlike an interface, the abstract class will allow you to provide implementations at the parent level (e.g.: saving the object to disk or database). You can read more here: https://msdn.microsoft.com/en-us/library/sf985hc5.aspx.
I also agree with Filkolev, this doesn't sound like something that you would want a static class for.
Does anyone come across with some older C# code as below, what would the equivalent in order to over come the later compiler error "'car' is a 'namespace' but is used like a 'type'".
Many thanks in advance.
namespace something.car
{
public class Display : UserControl
{
private car _car; // comppiler error here
public car carConfig // comppiler error here
{
get
{
return this._car;
}
set
{
this._car = value;
}
}
}
}
Change your first line from namespace something.car to
namespace Something.SomethingElse
and make sure you have a class car defined somewhere which you use in lines private car _car; and public car carConfig.
As a side comment, it is quite common to spell namespaces and class names in Pascal notation, e. g. namespace Something and public class Car.
To be able to use it without changing the namespace name ("but for sure change the namespace name is the right way").
but you can use the file path for the class when you use it, so if the car class is namespace "SomenameSpace.Viechels"
then you could use like below to not have the above conflict:
SomenameSpace.Viechels.car _car;
SomenameSpace.Viechels.car _carConfig;
If I have a class that is based off another class, how do I access the properties of the first class if it can have any name? I was thinking of using generics to access the properties, but the generics are "generic" for a reason...
For example:
public class AGameInXNA : Microsoft.Xna.Framework.Game
{
int ExampleGameProperty;
}
// ... another class ... //
public class ReferenceToAGameInXNA
{
Game gameInstance;
public void SetGameInstance(Game game)
{
gameInstance = game;
}
public void SetExampleGameProperty()
{
gameInstance.ExampleGameProperty = 21; // I don't know the name of
// AGameInXNA, so I want to
// access it using a generic
// class.
}
}
I know that that does not work, so how would I use generics in this case to access the AGameInXNA's properties in another class if I don't know AGameInXNA's name?
EDIT: I am trying to make it so that I can reuse this code later on. I want to be able to have a class that is unknown, such as public class unknownclassname that extends another class, such as Microsoft.Xna.Framework.Game, and be able to access the class unknownclassname without directly calling/implementing it in the library code.
I would recommend looking into XNA Services.
So for example, you would create a service which could be as simple as an
interface IExamplePropertyService
{
int ExampleProperty { get; set; }
}
public class AGameInXNA : Microsoft.Xna.Framework.Game, IExamplePropertyService
{
int ExampleGameProperty { get; set; }
void Initialize()
{
// Do other initialization
Services.Add( typeof(IExamplePropertyService), this );
}
}
public class ReferenceToAGameInXNA
{
IExamplePropertyService propertyService;
public void GetGameInstance(Game game)
{
propertyService = (IExamplePropertyService)game.GetService( typeof(IExamplePropertyService) );
}
public void SetExampleGameProperty()
{
propertyService.ExampleGameProperty = 21;
}
}
Implement it, and register it with the Game component, then in your ReferenceToAGameInXNA, you would query for this service and store it (rather than the Game) for use later.
As a bonus benefit, The IExamplePropertyService no longer even needs to be implemented by the Game class, it could be implemented by any GameComponent.
This makes for an easy way to seperate classes from having to know about the inner workings of other classes in the Game. So long as the services exist somewhere, your ReferenceToAGameInXNA can be used.
I don't think generics are what you are actually looking for here. In your second class, just change the type of all of the gameInstance to the type of the class you created for your game, in this case AGameInXNA. There should only be a need for one subclass of the Game type in each XNA game. That will allow you to access any public members of AGameInXNA from the Reference class.
If this isn't what you are after, please give a more detailed explanation of what you are trying to accomplish and I'll try to help you.
I don't know XNA, but if you want to have several classes that inherit from Game and have the same property on all of them, you could create an abstract class that inherits from Game and let the other classes inherit from that instead.
(Also, your GetGameInstance() is badly named, because it sets the field, it doesn't get it. And it's probably better as property anyway.)
public abstract class GameBase : Microsoft.Xna.Framework.Game
{
public int ExampleGameProperty { get; set; }
}
public class AGameInXNA : GameBase
{
// code specific to AGameInXNA
}
public class ReferenceToAGameInXNA
{
public GameBase GameInstance { get; set; }
public void SetExampleGameProperty()
{
GameInstance.ExampleGameProperty = 21;
}
}
If the other classed that have ExampleGameProperty shouldn't inherit from Game, you could create an interface instead. AGameInXNA would then inherit from Game directly and it would also implement the interface. And you would work with that interface in ReferenceToAGameInXNA.
using "Game gameInstance;" you can not acess ExmpleProp. You should use "AGameInXNA gameInstance;" too access ExampleProp.