I'm just getting to grips with Object Oriented Programming and I am stuck on how multiple objects are created without explicit defining in the code. For example in a while loop, setting a name and age for a dog, creating an object for it, and then giving it a unique identifier.
This is probably a simple question and I am missing something obvious but I can't get my head around it and some help would be appreciated. I have tried looking before but I can't find anything that helps.
Thanks
Edit:
I've been asked for some code as an example. Strictly speaking, I'm not stuck on a specific problem, more of a general question but I was thinking of something along the lines of the following
class Dog(self,name,age):
#Class stuff
while True:
dog_name=input("Enter dog name: ")
dog_age=input("Enter dog age: ")
dog=Dog(dog_name,dog_age)
My aim of this is to create multiple dog objects with different names/ages. However, I am worried that I will not be able to target a specific dog later in the code since they will all be saved as "dog". Is there any way of looping this to create something along the effect of dog1, dog2, dog3 etc. or is there another way of doing it entirely?
Good question! I would recommend using a list, which has slightly different syntax in different languages, looks like python so I'll give a python example
dogs = [] # this starts out as an empty list
while True:
dog_name = input("Enter dog name: ")
dog_age = input("Enter dog age: ")
dogs.append(Dog(dog_name, dog_age)) # creates a dog then adds it to the list
Say you do this and enter 3 dogs: Hope, Betsy, and Basil. They are 6, 2, and 12 respectively
then dogs[0] is the first dog (lists start at 0). dogs[0].name is Hope, and dogs[0].age is 6
dogs[1].name is Betsy, and so on
Based on your example, you're absolutely correct: you'd be unable to access each Dog instance after leaving the loop it was created in.
Using a class definition like:
public class Dog
{
public string Name { get; set; }
public int Age { get; set; }
}
There is nothing stopping you from instantiating an object of type Dog inside a loop:
using System;
while(true)
{
var dog = new Dog();
dog.Name = Console.ReadLine("Enter dog name: ");
dog.Age = int.TryParse(Console.ReadLine("Enter dog age: "), out int age) ? age : 0;
}
The class Dog still exists after each loop, and we recreate the dog variable each iteration, but the value of dog is not the same and is not recoverable.
If you need to use the value of each instance later, you will need to save them as you are executing each iteration of the loop.
This may look like saving every Dog:
using System;
using System.Collections.Generic;
var dogs = new List<Dog>();
while(true)
{
var dog = new Dog();
dog.Name = Console.ReadLine("Enter dog name: ");
dog.Age = int.TryParse(Console.ReadLine("Enter dog age: "), out int age) ? age : 0;
// Save this instance of the Dog class.
dogs.Add(dog);
}
foreach (Dog d in dogs)
{
Console.WriteLine($"{d.Name} is a good dog.");
}
Or saving just the oldest Dog:
using System;
var oldestDog = new Dog();
while(true)
{
var dog = new Dog();
dog.Name = Console.ReadLine("Enter dog name: ");
dog.Age = int.TryParse(Console.ReadLine("Enter dog age: "), out int age) ? age : 0;
// Save this instance of the Dog class if
// it is older than the current oldest dog
// (or if it's the first dog).
if (oldestDog is null || dog.Age > oldestDog.Age)
{
oldestDog = dog;
}
}
Console.WriteLine($"The oldest dog was {oldestDog.Age} year(s) old.");
Microsoft has a free course on variable scoping in C# if you are looking for a good place to learn more about scope in Object-Oriented languages.
Related
for (i in 0 until result.size){ result[i].config= addConfig(taskNames!![i],processKeys!![i]) }
Here result is a list of class which has datamember config and tasNames and processKeys are list of string.
Is there a way in kotlin to map result.config with respective taskNames and processKeys without using traditional loop and mentioning length of result.I am new to kotlin.
class Process {
var processKey: String? = null
var task: List<Task>? = null}
class Task {
var taskName: String? = null
var processVariables: List<ProcessVariable>? = null}
class ProcessVariable {
var name: String? = null
var label: String? = null
var applicableValue: List<String>? = null}
Result is already present with datamember config pf type ProcessVariable
If I understand your problem correctly, you need to combine 3 lists.
So iterating over the lists may be easier to understand than some clever way of list transformations.
You can get rid of the traditional for loop, so you don't need to calculate the size of the loop:
result.forEachIndexed {
i, resultData -> resultData.config = addConfig(taskNames[i], processKeys[i])
}
If you want to combine two lists, you can use the zip method:
val configList = taskNames.zip(processKeys) {tsk, prc -> addConfig(tsk, prc)}
In your example, the result-object was already existing. Maybe it is easier to create new result-objects:
val results = configList.map {
Result(config = it)
}
I'm building a sports product. I have 3 classes
class Team {
getName // ex: Los Angeles Lakers
getShortName // ex: Lakers
getAbbrName // ex: LAL
}
class Match {
Team getHomeTeam
Team getAwayTeam
Play[] plays
}
class Play {
Match getMatch
String description // "Kobe Bryant scores a 3 pointer!"
}
A team is just any sports team. A match is a sports match between two teams. During a match, plays happen that get attached to that match.
I have the need to get the home/away team's name, short name, and abbreviated names, given a Match or Play. Which option do you prefer and why?
Option 1 - callers need to do this. Ex:
class SomeCaller {
foo() {
Play play = // somehow get a play;
Match match = play->getMatch;
Team home = match->getHomeTeam;
Team away = match->getAwayTeam;
String homeTeamName = home->getName;
String homeTeamShortName = home->getShortName;
String homeTeamAbbrName = home->getAbbrName;
String awayTeamName = away->getName;
String awayTeamShortName = away->getShortName;
String awayTeamAbbrName = away->getAbbrName;
// do something with the team names
}
}
Option 2 - Add the same methods to both classes
class Match {
Team getHomeTeam
Team getAwayTeam
Play[] plays
String getHomeTeamName() {
Team homeTeam = getHomeTeam();
return homeTeam->getName();
}
// same as above...
String getHomeTeamShortName()
String getHomeTeamAbbrName()
String getAwayTeamName()
String getAwayTeamShortName()
String getAwayTeamAbbrName()
}
class Play {
Match getMatch
String getHomeTeamName() {
Match match = getMatch;
return match->getHomeTeamName();
}
// same as above...
String getHomeTeamShortName()
String getHomeTeamAbbrName()
String getAwayTeamName()
String getAwayTeamShortName()
String getAwayTeamAbbrName()
}
Keep in mind I would want to get name, short name, abbr name, for both home and away teams given a Match or Play object, so there's going to be lots of method duplication with option 2.
Option 1 is prefered of the two.
Typically you wouldn't have a reference from Play to Match and Match to Play.
class Team {
getName // ex: Los Angeles Lakers
getShortName // ex: Lakers
getAbbrName // ex: LAL
}
class Match {
Team getHomeTeam
Team getAwayTeam
Play[] plays
}
class Play {
String description // "Kobe Bryant scores a 3 pointer!"
}
Now, you won't be able to get the team names with only a Play, but if you have access to all the matches you can do something like this:
foreach(match in matches)
foreach(play in match)
if(play == desiredPlay)
doSomething
If this isn't acceptable, in case you need to get team names from only a play, without knowing the matches, you would have a reference to this directly in your play. I.e:
class Play {
Team getHomeTeam
Team getAwayTeam
String description // "Kobe Bryant scores a 3 pointer!"
}
This couples your code more than option 2, but less than option 1.
This is all because of "Law of Demeter" (https://en.wikipedia.org/wiki/Law_of_Demeter) which in a nutshell says, you shouldn't know of the Match, if it is what Match knows you really want, you should instead know of Team.
The link has a decent example I suggest you read. :)
I am implementing a book search function based on hibernate search3.2.
Book object contains a field called authornames. Authornames value is a list of names and comma is the splitter, say "John Will, Robin Rod, James Timerberland"
#Field(index = org.hibernate.search.annotations.Index.UN_TOKENIZED,store=Store.YES)
#FieldBridge(impl=CollectionToCSVBridge.class)
private Set<String> authornames;
I need each of names to be UN_TOKENIZED, so that user search book by single author name: John Will, Robin Rod or James Timerberland.
I used Luke to check indexs, and value in authornames field is stored as "John Will, Robin Rod, James Timerberland", but I can not get result by querying "authornames:John Will"
Anybody can tell me how can I do it?
I gues CollectionToCSVBridge is concatenating all names with a ", " in a larger string.
You should keep them separate instead and add each element individually to the index:
#Override
public void set(String name, Object value, Document document, LuceneOptions luceneOptions) {
if ( value == null ) {
return;
}
if ( !( value instanceof Collection ) ) {
throw new IllegalArgumentException( "This FieldBridge only supports collections." );
}
Collection<?> objects = (Collection<?>) value;
for ( Object object : objects ) {
luceneOptions.addFieldToDocument( name, objectToString( object ), document ); // in your case objectToString could do just a #toString
}
}
See also https://forum.hibernate.org/viewtopic.php?f=9&t=1015286&start=0
Let's say I have two entity objects "table" and "chicken."
Now let's say, I have a "wing" object, and I want that wing to have a 0..1-1 relationship with table and chicken. In otherwords, I want a nullable table.wing and a nullable chicken.wing.
Is there a good way, using Entity Framework 4, to make the wing object have the restriction that it can either be associated with a table OR a chicken?
Note: I don't want to have a wingedobjects baseclass in my dictionary- this needs to be a "has one" not an "is one."
My thought is that I can't make a unique restraint on the collection of references, so I'll have to wrap the Entity properties with something like:
public partial class Wing:
...
public Table Table
{
get { return this.Table; }
set {
//make sure Chicken is null
this.Table = value;
}
}
...
}
This strikes me as pretty hacky and not too clean, so I was looking for a better, if not best, practices solution.
Edit:
To be clear, I currently have a 0..1-1 relationship between table and wing, and a 0..1-1 relationship between chicken and wing. Thus, I can create a table.wing and I can then look at wing.table. What I want is to ensure that I ALWAYS have a null value if I query table.wing.chicken or chicken.wing.table. The wing must be associated with EITHER one table OR one wing.
Example of current behavoir:
In response to #morganppdx's comment:
Given this Entity Diagram:
And the following in Program.cs:
class Program
{
static void Main(string[] args)
{
Model1Container container = new Model1Container();
Wing chickenwing = new Wing { Shape = "birdlike" };
Chicken chicken1 = new Chicken { Breed = "Andalusian", Wing = chickenwing };
Table table1 = new Table { Style = "Mission", Wing = chickenwing }; // Should throw exception!
container.AddToChickens(chicken1);
container.AddToTables(table1);
container.SaveChanges();
Console.Write(String.Format("Table {0}'s wing has a {1} shape...", table1.Id, table1.Wing.Shape));
Console.Write(String.Format("Table {0} has {1} chicken wings!", table1.Id, table1.Wing.Chicken.Breed));
Console.ReadLine(); //wait for input to give us time to read
}
}
The resulting console will show:
Table 1's wing has a birdlike shape...Table 1 has Andalusian chicken wings!
This result is what I wish to avoid. It should throw an exception when chickenwing is associated with table1 because it is already associated with chicken1, and cannot be associated with both a table and with a chicken.
It is quite possible that I am building the relationship incorrectly, and thus not getting #morganpdx's stated exception where I want it.
The code is available at: https://github.com/mettadore/WingThing
Off the top of my head, my suggestion would be to create child objects that extend the Wing object, and use those instead of your Wing object:
public class ChickenWing : Wing
{
public Table Table { get { throw new NoTablesAllowedException; }}
}
public class TableWing: Wing
{
public Chicken Chicken { get { throw new NoChickensHereException; }}
}
The code you posted would then look like this:
class Program
{
static void Main(string[] args)
{
Model1Container container = new Model1Container();
ChickenWing chickenwing = new ChickenWing { Shape = "birdlike" };
TableWing tablewing = new TableWing { Shape = "circular" };
Chicken chicken1 = new Chicken { Breed = "Andalusian", Wing = chickenwing };
Table table1 = new Table { Style = "Mission", Wing = tablewing };
container.AddToChickens(chicken1);
container.AddToTables(table1);
container.SaveChanges();
Console.Write(String.Format("Table {0}'s wing has a {1} shape...", table1.Id, table1.Wing.Shape));
Console.Write(String.Format("Table {0} has {1} chicken wings!", table1.Id, table1.Wing.Chicken.Breed));
Console.ReadLine(); //wait for input to give us time to read
}
}
I have not done anything like this to date, but I believe this should work. Essentially the Wing object acts as an Interface to describe the ChickenWing and TableWing objects, but those are discreet objects used for discreet purposes.
Looking on your model I think you can simply make Table and Wing Ids as IDENTITY with different seed and increment 2 - one will have only even and second only odd Ids and in such case there will never be wing which will be related to both.
The point is that one-to-one relation in EF is always built on primary keys so wing must have primary key of either table or chicken and when defining exclusive sequences it will never happen that wing can have both table an chicken.
I have 3 classes like:
public class Animal
{
... all sort of data ...
}
public class Cat : Animal
{
... more data ...
public virtual int Size { get; set; }
}
public class Dog : Animal
{
... other data ...
public virtual int Size { get; set; }
}
The classes are mapped using the "table per hierarchy" strategy in the hbm.xml mapping the Cat's Size property is mapped to a CatSize column and the Dog's property to DogSize
The following two queries work as expected:
From Cat o Where o.Size = 1
From Dog o Where o.Size = 1
Now I want to query Animal for all the cats where Size = 1 and all the dogs where size = 1, combining the two queries above I get:
From Animal Where o.Size = 1 Or o.Size = 1
That obviously doesn't do what I want, how can I tell NHibernate the first Size is Cat.Size and the second is Dog.Size (preferably without knowing the column names in the database).
Note: I understand the design is problematic an having two properties with the same name in different subclasses is not the smartest design decision ever made - but changing it now is even more problematic and I'd like to avoid it (the project should be delivered to the client in a few days and I really don't want to make design changes now).
I'm using NHibernate 2.0.1 (upgrading is not an option, the program does not work with later versions of NHibernate and we don't have time to fix it now).
Try this...
select a from Animal a where a in (select c from Cat c where c.Size = 1) or a in (select d from Dog d where d.Size = 1)
Why didn't you define the Size property on the Animal class ?
You can use a MultiQuery to execute the 2 queries in one roundtrip, and that will give you the results as well.
I think that this will be the best solution ...
IMultiQuery q = session.CreateMultiQuery();
q.Add("from Cat where Size = 1");
q.Add("from Dog where Size = 1");
var results = q.List();
var cats = (IList)results[0];
var dogs = (IList)results[1];