0

I want to ask something in object oriented programming: I have built the following software: i have an abstract class: Aapartment

abstract class Aapartment
{
    public int roomNumbers { get; set; }
    public int price { get; set; }  
}

in addition, another two classes:

class Private:Aapartment
{
    public Private() { }
    public Private(int price,int roomN)
    {
        this.price = price;
        this.roomNumbers = roomN;
    }
}

class penthouse:Aapartment
{
    public penthouse() { }
    public penthouse(int price,int roomN)
    {
        this.roomNumbers = roomN;
        this.price = price; 

    }
}

I have also created the following class which derives from ArrayList class:

class AllApartments : ArrayList
{
    public AllApartments() 
    {
    }

    public Aapartment Search(int price, int roomN, string type)
    {
        Aapartment temp = null;
        for(int i=0;i<this.Count;i++)
        {
            if ( (((Aapartment)this[i]).price == price) && (((Aapartment)this[i]).roomNumbers == roomN))
            {
                 if (((Aapartment)this[i]).GetType().Name.ToString().Equals(type))
                 {
                     temp =  (Aapartment)this[i];
                 }
            }   
        }

        return temp;
    }
}

The main program is :

static void Main(string[] args)
{
    AllApartments all = new AllApartments();
    all.Add(new Private(200000000, 5));
    all.Add(new penthouse(125000000, 4));
    all.Add(new penthouse(125000000, 2));
    all.Add(new penthouse(125000000, 7));
    all.Add(new penthouse(125000000, 1));

    int roomN;
    int price;
    string type1;

    type1 = Console.ReadLine() ;
    //Type type = Type.GetType("ConsoleApplication48.Aapartment");
    roomN = Convert.ToInt32(Console.ReadLine());
    price = Convert.ToInt32(Console.ReadLine());

     Aapartment temp =  all.Search(price, roomN, type1);
    Console.WriteLine(temp.GetType().ToString()); 
}

My question is: Is there any option to define Apartment variable instead of string in the search function of AllApartments class, and compare it with the string variable the user enter in the console? I have used the following code: .GetType().Name.ToString().

Ageonix
  • 1,748
  • 2
  • 19
  • 32
Sefit
  • 1
  • 1
  • 8
    [How do I write a good title?](http://meta.stackexchange.com/q/10647/158761) – Soner Gönül Mar 04 '16 at 13:39
  • 5
    You should not use Arraylists, and even if you did you shouldn't really inherit from them. Look at generics instead. All of that casting would then go away. – Steve Mar 04 '16 at 13:40
  • 2
    This is not to solve your question but more of little nitpicking (if you don't want to call it *advice*) **be very careful when you write your class name** your `Private` (`class` name) and the `private` (keyword) is *very very* similar... – Ian Mar 04 '16 at 13:41
  • 2
    The code has many problems, but the main problem is that you're using inheritance to denote a difference in apartment type. You don't want to recompile and redistribute your application when a user wants to add a new apartment type. Make `ApartmentType` a string property. – CodeCaster Mar 04 '16 at 13:45
  • I get that this is just an exercise, but using different types for appartments/privates/penthouses really doesn't add anything here, it just makes stuff more complicated. Also, don't use `ArrayList`; use `List instead. – Rik Mar 04 '16 at 13:45
  • Basically: you do not know how to use generics. – TomTom Mar 04 '16 at 13:45
  • @CodeCaster wait what? I can understand preferring composition/interfaces over abstract base classes, but denoting an objects type (and behavior) using a primitive string is not extensible OR object-oriented, it's not type safe, nor does it really improve the code at all. a new apartment type with new behavior will warrant recompiling SOMETHING no matter what you do. why would you be so scared of deploying a new version when you add a new feature? – sara Mar 04 '16 at 14:14
  • @kai there is no behavior shown here. They're all apartments that can be rented. From that viewpoint, there is no difference between a cardboard box and a castle: you pay rent, you get to occupy it, that's it. – CodeCaster Mar 04 '16 at 14:26
  • @CodeCaster I think this would only suggest that the question is a "minimal verifiable example", as per SO recommendation. But even if there was no behavior at all, your approach is still not type safe, and is not extensible. what happens the day you DO want behavior, even if there is none today? is "678´+►♣§☻" a valid apartment type? and what if you want to register 2 penthouse apartments, but accidentally make one of them a "oenthouse"? if anyone at all is interested in searching or grouping by the type, using a primitive string is downright awful and with no real advantages imo. – sara Mar 04 '16 at 14:42
  • @kai look; this obviously is meant to be an apartment reservation system of some sort. A reservation is not handled differently for different apartment types. There will be a database backing the system; there will be an UI presenting the selection options. All of this will be handled using strings. You simply do not use inheritance in this case to differentiate between different types. Compare it to a library checkout system: are you going to introduce a class per book genre, or will it have a `List Genres` property? KISS, YAGNI, and so on. – CodeCaster Mar 04 '16 at 14:44
  • @CodeCaster no, I would not make a class hierarchy with one class per instance of a genre, and you won't find any book on OOP principles and patterns that recommends you to. the concept of a Genre should be encapsulated as a class that you can create genre instances from. if all you have is a string, how do you change the name of a genre without having to migrate a million db rows? how do you compare 2 genres? OrdinalIgnoreCase? how do you localize? this isn't YAGNI, it's primitive obsession, and most certainly isn't OOP. – sara Mar 04 '16 at 14:56
  • @kai sure, a `List` foreign key relation then, but certainly not inheritance. I'm not suffering from primitive obsession, I'm trying to steer the OP away from applying an OO hammer where other, better tools exist. – CodeCaster Mar 04 '16 at 15:02

3 Answers3

2

I would not create AllApartments but use a List and then create a search method :

        private List<Aapartment> _appartements;

    public Aapartment Search(int price, int roomN, Type type)
    {
        var founded = _appartements.SingleOrDefault(x => x.GetType() == type && x.price == price && x.roomN == roomN);
        return founded;

    }

More on lambdas with linq queries : https://msdn.microsoft.com/fr-fr/library/bb397675.aspx

For the program, I would ask to the user 0 for penthouse and 1 for private, it's bad design to map the user input to the type name.

     static void Main(string[] args)
    {
        AllApartments all = new AllApartments();
        all.Add(new Private(200000000, 5));
        all.Add(new penthouse(125000000, 4));
        all.Add(new penthouse(125000000, 2));
        all.Add(new penthouse(125000000, 7));
        all.Add(new penthouse(125000000, 1));

        int roomN;
        int price;
        int type1;

        type1 = int.Parse(Console.ReadLine());
        //Type type = Type.GetType("ConsoleApplication48.Aapartment");
        roomN = Convert.ToInt32(Console.ReadLine());
        price = Convert.ToInt32(Console.ReadLine());
        Type type;
        switch (type1)
        {
            case 0 :
                type = typeof (penthouse);
                break;
            case 1:
                type = typeof (Private);
                break;
            default:
                throw new Exception("Appartment type unknown");
        }

        Aapartment temp = all.Search(price, roomN, type);
        Console.WriteLine(temp.GetType().ToString());
    }

I used an int but you could use an enum;

Pak
  • 2,639
  • 2
  • 21
  • 27
  • and when i call the search function , what do i pass to it ? for example: search ( 100,5,?) – Sefit Mar 04 '16 at 14:40
0

You could have a readonly property that returns that.

public string TypeName { get { return GetType().Name; } }
Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
0

This isn't Code Review and this looks like an XY problem incited by homework requirements, but here goes.

You're trying to apply inheritance, a strong object-oriented design principle, to a problem where it doesn't fit. You should only use inheritance to add behavior that derives from the base class behavior.

If I may try to extract the original requirements from your question:

I want to create an apartment reservation system, where a user can search for an apartment type.

You don't need inheritance for this. Just as you wouldn't create a Novel : Book class, a ScienceFiction : Book class and a Dictionary : Book class when you're building a library checkout system (not in the first place because a book can have many genres), so shouldn't you when building this apartment reservation system.

The type of an apartment for rent is just a propery of the non-abstract Apartment class. It doesn't add new behavior, it's not something that makes the Apartment class suddenly not fit to hold a "Cardboard Box" nor a "Castle" type of apartment.

So for the sake of simplicity, keep it a string property:

public class Apartment
{
    public int NumberOfRooms { get; set; }
    public int Price { get; set; }  
    public string Type { get; set; }
}

And then the entire need for this question goes away. Of course you could also make Type an enum, for type-safety (or typo-safety).

Furthermore, you don't use ArrayList and you don't inherit from a List (again, you don't add behavior to the list, so don't inherit from it), but just use a List<T>:

var apartmentData = new List<Apartment>
{
    new Apartment { NumberOfRooms = 4, Price = 42000, Type = "Private" },
    new Apartment { NumberOfRooms = 40, Price = 420000, Type = "Penthouse" },
    new Apartment { NumberOfRooms = 400, Price = 4200000, Type = "Castle" },
};

Then you can use a "repository"-like pattern to create your unique logic:

public class ApartmentRepository
{
    private readonly List<Apartment> _apartmentData;

    public ApartmentRepository(List<Apartment> apartmentData)
    {
        _apartmentData = apartmentData;
    }

    public Apartment Search(int price, int numberOfRooms, string type)
    {
        return _apartmentData.FirstOrDefault(a => a.Price == price 
                                               && a.NumberOfRooms == numberOfRooms
                                               && a.Type == type);
    }
}

Besides all that, you should in general favor composition over inheritance. You might say "But my occupants will enter the building in a different way!" (if that's even relevant to the system).

Then you simply add a IWayOfEntry WayOfEntry property to the Apartment (or maybe Residency is a better class name anyway), to which you then assign a DrawBridge, Elevator or FrontDoor instance, while Residency.Enter() simply relays the call to WayOfEntry.Enter().

Community
  • 1
  • 1
CodeCaster
  • 147,647
  • 23
  • 218
  • 272