Method redefinition and polymorphism

I am trying to create a program that allows a user to register in a hotel room. The program should check if the room is free, and then select one of the free rooms, if any. I have several types of rooms, such as a single room, a double room, a twin room, etc., which everyone should inherit from the basic class Room .

Here is my code now.

 public class Room { public static bool[] av = { false, true, false }; public bool availability() { bool a = false; foreach (var roomAv in av) { a = a || roomAv; } return a; } public bool availability(int room) { return av[room]; } public int allocate() { if (availability()) { int room = 0; while (!av[room]) { room++; } av[room] = false; return room; } else { return -1; } } public static void roomStatus() { for (int i = 0; i < av.Length - 1; i++) { Console.WriteLine(i + av[i].ToString()); } } } class SingleRoom { } 

The functions that I defined in the room class should be used by all types of rooms, but each of them has its own separate array, indicating whether they are available or not. How can i do this? How can I access these functions for each class, but there is a separate separate array instead of executing them only in the "av" array, as it is currently.

+6
source share
5 answers

As you said, you are new to C #, I would suggest revising the structure. You are in an object oriented paradigm. What you think is simple C-function oriented programming.

 public class Room { public bool IsAvailable {get; set;} public RoomType RoomType {get; set;} public int RoomNo {get; set;} public int Floor {get; set;} public string RoomName {get; set;} } public enum RoomType { Single, Double, Twin, King, HoneymoonSuite } public class RoomManager { public List<Room> AllRooms {get; set;} public RoomManager() { AllRooms = new List<Room>(); AllRooms.Add(new Room(){ RoomType=RoomType.Single, RoomNo=1, Floor=1, RoomName="A101", IsAvailable=true}); AllRooms.Add(new Room(){ RoomType=RoomType.Double, RoomNo=2, Floor=1, RoomName="A102", IsAvailable=false}); AllRooms.Add(new Room(){ RoomType=RoomType.HoneyMoonSuite, RoomNo=1, Floor=2, RoomName="A201", IsAvailable=true}); } public bool IsAvailable(int roomNo) { //You need to check if roomNo is a valid RoomNo return AllRooms.Any(r=>r.RoomNo==roomNo && r.IsAvailable); } public bool IsAvailable(string roomName) { //You need to check if roomName is valid RoomName return AllRooms.Any(r=>r.RoomName==roomName && r.IsAvailable); } } 
+2
source

The functions defined in the class of the room should be used all types of rooms, but each of them has its own separate array that they are available or not. How can i do this?

When you use the static for a variable, you say that the variable belongs to the type itself and not to the object instance. Quoting from MSDN docs :

Use the static modifier to declare a static member that belongs to the type itself, and not to a specific object.

In other words, your array "belongs" to the Room class, and not to individual Room objects created using new . If you want each instance of the object to have its own private member variables, then you must remove the static . I.e.

 public static bool[] av = { false, true, false }; 

it should be:

 public bool[] av = { false, true, false }; 

Note that the same applies to method names, that is, if you use the static for a method, this method "belongs" to the class / type itself, and not to instances of individual objects. This means that your roomStatus method should be used as Room.roomStatus() , and trying new Room().roomStatus() not possible.

I would recommend deleting the array and turning it into a property so that you can just do something like:

 Room r = new SingleRoom(); if(r.IsAvailable) { // ... } 

You should also reorganize your code to follow the .NET naming conventions for your methods, variable names, and better use object orientation. I think the Niraj Doshi message is a good step in that direction.

Since you are new to C #, I would recommend that you get B. Wagner's book Effective C #.

Update - Implemented Code

This is my attempt to refactor code that has a RoomManager interface, a IRoom , an abstract implementation of the IRoom interface called Room with code and functionality common to all rooms, a specific SingleRoom for a more specific type and TextView class to control how the data will be displayed / displayed to the user (i.e. text output).

Note that this happens after the Model-View-Controller (MVC) design pattern, with the Room classes being models (i.e. data), TextView is responsible for displaying the data (i.e. presentation), and the main program itself is the controller (i.e. coordinates the other two).

Home Program

The program simply adds some rooms, and then displays information for each of them based on the capabilities of the manager.

 using System; using System.Collections.Generic; namespace HotelRoomManager { class MainClass { public static void Main (string[] args) { RoomManager mgr = new RoomManager (5); for (uint i = 0; i < mgr.Capacity; ++i) mgr.AddRoom (new SingleRoom (1, i + 1) ); List<IRoom> rooms = mgr.GetAllRooms (); TextView view = new TextView (); view.RenderHeader (); view.RenderModels (rooms); mgr.RemoveAllRooms (); } } } 

IRoom Interface

The interface determines the type and is the basis for all rooms. Interfaces are used to define contracts with customers and are independent of implementation details, which makes it a good object-oriented practice.

 using System; namespace HotelRoomManager { public enum BedType { Single, Double, Twin, Queen, King } public interface IRoom { BedType BedType { get; } uint Floor { get; } uint Number { get; } bool IsOccupied { get; set; } } } 

Abstract Room

The room simply contains a code that is common to all rooms, regardless of their individual details.

 using System; namespace HotelRoomManager { public abstract class Room : IRoom { private uint floor; private uint number; private bool occupied; public Room (uint floor, uint number) { this.floor = floor; this.number = number; occupied = false; } public uint Floor { get { return floor; } } public uint Number { get { return number; } } public abstract BedType BedType { get; } public bool IsOccupied { get { return occupied; } set { occupied = value; } } override public string ToString() { return "Room(floor=" + floor + ", number=" + number + ")"; } } } 

Concrete SingleRoom

At this point, this room should only communicate its actual type. There is no need to do anything special in addition to an existing common function.

 using System; namespace HotelRoomManager { public sealed class SingleRoom : Room { public SingleRoom (uint floor, uint number) : base(floor, number) {} override public BedType BedType { get { return BedType.Single; } } } } 

RoomManager

The manager simply helps keep track of all rooms and provides a simplified interface for interacting with the collection.

 using System; using System.Collections.Generic; namespace HotelRoomManager { public class RoomManager { private List<IRoom> rooms; public RoomManager (uint capacity) { rooms = new List<IRoom> (); rooms.Capacity = (int) capacity; } public void AddRoom(IRoom room) { rooms.Add (room); } public void RemoveRoom(IRoom room) { rooms.Remove (room); } public List<IRoom> GetAllRooms() { return rooms; } public void RemoveAllRooms() { rooms.Clear (); } public uint Capacity { get { return (uint) rooms.Capacity; } } } } 

TextView

The sole responsibility for the presentation is to decide how the data from the models will be presented to the user. This separates the data from the way the data is displayed, which simplifies the maintenance and expansion of your system. You can also use several types of views instead of selecting one or the other.

 using System; using System.Collections.Generic; using System.Text; namespace HotelRoomManager { public class TextView { public TextView () {} public void RenderHeader() { Console.WriteLine ("Hotel Management System"); Console.WriteLine ("-----------------------"); } public void RenderModels(List<IRoom> rooms) { StringBuilder sb = new StringBuilder (); foreach (IRoom r in rooms) { sb.Append ("Floor : " + r.Floor + "\n"); sb.Append ("Number : " + r.Number + "\n"); sb.Append ("Bed : " + r.BedType + "\n"); sb.Append ("Occupied: " + (r.IsOccupied ? "Yes" : "No") + "\n\n"); } Console.WriteLine (sb.ToString ()); } } } 

Output

A quick launch of the program will lead to the following conclusion:

 Hotel Management System ----------------------- Floor : 1 Number : 1 Bed : Single Occupied: No Floor : 1 Number : 2 Bed : Single Occupied: No Floor : 1 Number : 3 Bed : Single Occupied: No Floor : 1 Number : 4 Bed : Single Occupied: No Floor : 1 Number : 5 Bed : Single Occupied: No 
+2
source

It is quite simple, instead of a field, use the property:

 public class Room { public virtual bool[] av { get; set; } = { false, true, false }; //All of your functions remain unchanged except you need to remove static } 

Then in your derived classes:

 public class SingleRoom : Room { public override bool[] av { get; set; } = { true, true, false }; } 

An array will be installed in the legacy rooms, which will be used in the basic functions for accessibility, so you only need to write it once.

This is another plus of properties over fields where you can set a property so that it can be inherited. The only thing that was really โ€œwrongโ€ with your source code was that the array and some methods were declared static , which means that it was the same in all instances of the class. Availability should be an instance level field / property, not a level level.

Your source code may work if you remove static and make your derived classes as follows:

 public class SingleRoom { public SingleRoom : base() { //Redefine the values of the array. av = { true, true, false }; } } 
+1
source

You put the array as static , which means that all access to the array reaches the same object.

Remove it and each of them will have its own.

According to the comments, the static identifier should be removed from the roomStatus method.

0
source

Well, inheritance is used for this. You can create an abstract class and define common logic for all your specific classes, as well as their common members:

 abstract class AbstractRoom { public bool[] av; public bool availability() { // some logic } public bool availability(int room) { // some logic } public int allocate() { // some logic } public void roomStatus() { // some logic } } class MyConcreteRoom1 : AbstractRoom { } class MyConcreteRoom2 : AbstractRoom { } 

Then you can do something like:

 List<AbstractRoom> rooms = new List<AbstractRoom>() { new MyConcreteRoom1(), new MyConcreteRoom2() }; rooms[0].availability(); rooms[1].availability(); 
0
source

All Articles