Jump to content
ytinU

Duda clases

Recommended Posts

Hola a todos.

Estaba revisando herencia en la web y me encontre una sorpresa(por lo menos para mí), crear una herencia para collider(donde le des sonido, efectos, etc de acuerdo al collider) y pues yo no sabia eso, si bien sé algo de herencia y polimorfismo queria comprobar lo que sé con los expertos en este tema.

Las clases solo aceptan atributos de tipo básico(int.float) y no cosas que hereden de monobehaviur, así que como hacen ustds para acceder a ellos?.. crean atributos nombreefecto.. ponen el nombre del efecto en el constructor y ponen un if.. algo así.

public class collider{
  int vida;
  string nombreefect;
  public collider(int vidita,string ne){
  vida=vidita;
    nombreefect=ne;
  }
  //metodos..
  .
  .
  //más métodos
    .
    .
}
-
  -
  -
  -
public class claserandom:Monobehaviur{
 collider asd=new collider(70,"explota");
  void oncollisionenter(collision x){
  	if(asd.nombreefect=="explota"){
    	print("KABOOM");
      //accion efecto de particulas mostrar letras(UI) o cualquier cosa
      //cosas que heredan de mono..
      //si es la comparacion correcta entre string(del padre) a accion que hereda de monobehaviur
      //el print es un ejem
    }
  }
}

es así alguna forma correcta de hacerlo, porque lo que quiero hacer como tengo 5 padres y como 40 hijos quiero centrarme en la optimización y si es que existe algo más optimizable.

Share this post


Link to post
Share on other sites
7 hours ago, ytinU said:

Las clases solo aceptan atributos de tipo básico(int.float) y no cosas que hereden de monobehaviur,

Si creas una clase podes crear cualquier objeto dentro, no solo int, foat, etc. Por ejemplo un GameObject. fijate que casi todo es un Object y tambien tienen sus metodo que funcionan en cualquier lado:

https://docs.unity3d.com/ScriptReference/Object.html

la cosa esta en que vos llamas a esos GetComponent dentro de OnEnable, awake, start, update ,etc.. que forman parte de todo monobehaviour, no podes hacerlo desde la misma definicion de una clase cualquiera.

No entendi muy bien a que Collider te referis, al que pusiste en tu clase o a la clase Collider de Unity? porque el que pusiste vos no hereda de nada por eso pregunto.

Share this post


Link to post
Share on other sites
hace 4 minutos, lightbug said:

Si creas una clase podes crear cualquier objeto dentro, no solo int, foat, etc. Por ejemplo un GameObject. fijate que casi todo es un Object y tambien tienen sus metodo que funcionan en cualquier lado:

Una clase que no herede de Monobehaviour hereda la clase Object? tengo entendido que crear una clase sola solo puede usar los tipos primitivos o solo es necesario las librerias?

hace 8 minutos, lightbug said:

la cosa esta en que vos llamas a esos GetComponent dentro de OnEnable, awake, start, update ,etc.. que forman parte de todo monobehaviour, no podes hacerlo desde la misma definicion de una clase cualquiera.

Lo que queria hacer el crear una clase padre y otra que herede de monobehaviour además de la clase padre.

hace 13 minutos, lightbug said:

No entendi muy bien a que Collider te referis, al que pusiste en tu clase o a la clase Collider de Unity? porque el que pusiste vos no hereda de nada por eso pregunto.

-La clase collider es una clase mia, fue un error poner el mismo nombre que la de unity, puede llamarse collidermio...

-Supongo que bastara con poner :collider(mi clase) al costadito de Monobehaviour, lo que pasa es que solo usaba clases en java y hace tiempo que no lo toco, ni tampoco lo he hecho en c# y pues es la poca practica..

Share this post


Link to post
Share on other sites
7 hours ago, ytinU said:

Una clase que no herede de Monobehaviour hereda la clase Object? tengo entendido que crear una clase sola solo puede usar los tipos primitivos o solo es necesario las librerias?

Nono, una clase por si sola no hereda de nada. Cuando vos pones arriba using UnityEngine podes definir un Object dentro de una de esas clases o afuera, no necesariamente int,floats,etc.

7 hours ago, ytinU said:

Lo que queria hacer el crear una clase padre y otra que herede de monobehaviour además de la clase padre.

No podes heredad de multiples clases.

Si lo que queres hacer es que el padre sea el "tipo" y el hijo sea uno de esos "tipos" podes usar clases abstractas(no podes crearlas solos sus derivados) o no, pero es mas lindo ponerla abstracta para definir mas "la cosa".Ejemplo:

public abstract class Enemy : Monobehaviour
{
	//datos de todo enemigo, salud, daño, etc
}

public class EnemyZombie : Enemy	//hereda de Enemy que es un monobehaviour
{
	//datos unicos zombi
}

public class EnemyVampiro : Enemy	//hereda de Enemy que es un monobehaviour
{
	//datos unicos Vampiro
}

Tambien podes valerte de Interfaces, que son esas que tienen la "I" generalemtne adelante (Ej IEnumerator), en donde declaras funciones, ejemplo:

public interface IPepe
{
	void PepeA();
	void PepeB();
}

public class MiClase : Monobehaviour , IPepe
{
	//tenes que definir las funciones de IPepe sino da error
	//podes usar otra definicion completamente diferente en otras clases

	public void  PepeA(){ .... }
	public void  PepeB(){ .... }
}

Fijate que parece que hereda de mcuhas clases, o por lo menos se ve asi, pero simplemente le impones a tu clase que implemente los metodos que declaraste dentro de la interfaz. Podes heredar de todas las interfaces que quieras.

En fin, son herramientas, pensa cual se asemeja a lo que queres y usala.

Share this post


Link to post
Share on other sites
hace 9 minutos, lightbug said:

Si lo que queres hacer es que el padre sea el "tipo" y el hijo sea uno de esos "tipos" podes usar clases abstractas(no podes crearlas solos sus derivados) o no, pero es mas lindo ponerla abstracta para definir mas "la cosa".

Osea por lo poquito que entiendo ya mañana lo investigare más lo de abstract en clase es una base no instanciable que sirve como plantilla para los hijos, osea veo que solo es para instanciar los hijos(que es lo que quiero), la mayor duda que es la optimización es cual es la diferencia en poner funciones en enemyvampiro a implementar interfaces supongo que son como miniherencia.. osea puede ser una interfaz padre y generalizarlo mucho para que otras clases lo implementen para ahorrar espacio y lo más especifico como 'chupar sangre' sea una función especifica de enemyvampiro?.. lo digo porque yo acostumbre a utilizar una clase padre y 3 hijos como maximo con los tipicos ejercicios de facultad por eso mi insistencia con el performance, pero basicamente tu respuesta resolvio mis dudas solo que brotaron más dudas xD.

Share this post


Link to post
Share on other sites
7 hours ago, ytinU said:

osea puede ser una interfaz padre y generalizarlo mucho para que otras clases lo implementen

Si, esa es la idea de las interfaces, vos miras que dice y te das cuenta, o quizas creas una clase y queres que el objeto de la clase haga daño, entonces le metes tu "IDamage" por ejemplo e implementas tu metodo Damage(). Quizas implementas un daño elemental y de fuego, y para tu otra clase que implementaste la misma interfaz le pones quee haga daño por rebote y acido, que se yo. Basicamente llevan las declaraciones, yo no las uso mucho para no enquilombar mas lo que tengo defino todo en mis clases y listo. No creo que existe "LA" diferencia, aunque si queda todo mas prolijo.

7 hours ago, ytinU said:

y lo más especifico como 'chupar sangre' sea una función especifica de enemyvampiro?

La definis dentro de la clase vampiro y es especifica de ahi. Nadie la puede usar salvo un vampiro.

Share this post


Link to post
Share on other sites

A vale, tengo otra duda sobre el constructor por ejem..

public abstract class player:Monobehaviour{
  
  private int vida;
  private float velocidad;
  private Gameobject arma;//creo que es mejor ponerla de tipo arma
  
  public claserandom(int vidita,float velo, Gameobject arm)//lo mismo
  {
  	vida=vidita;
    velocidad=velo;
    arma=arm;
  }
  //métodos get/set
  .
    .
    .
    .
  
}
public class luchador:player{
  private int fuerzadepatada;
  private float salto;
  
  //aqui no se como agregar atributos a la clase base, pienso que es agregando a su constructor
  public luchador(int x, int y, arma arm, int fuerzapat,float salt):base(vidita,velo,arm){
    
    fuerzadepatada=fuerzapat;
    salto=salt;
    
  }
  //o debo jalar los get/set del padre y crear un nuevo constructor en el hijo
  //lo que quiero hacer es que al llamar a luchador acepte atributos del padre hijo en el contructor
}

Vale recien me entero que no es necesario crear get/set solo poner base.nombreatribute.

Edited by ytinU

Share this post


Link to post
Share on other sites

Si queres que un campo sea accesible para las clases derivadas tenes que usar protected, si vas a  usar clases abstractas usa protected ya que nunca vas a tener una instancia de dicha clase. Por ejemplo:

public abstract class Actor : Monobehaviour
{
	protected int m_health;
	protected string m_name;
}

public class Player : Actor
{
	public Player(string name, int health)
	{

	}
}

public class Enemy : Actor
{
	public Enemy(string name, int health)
	{

	}
}

 

Share this post


Link to post
Share on other sites

Entonces nunca crear constructor en padre sino en el hijo y usar atributos del padre no?

Share this post


Link to post
Share on other sites
7 hours ago, ytinU said:

Entonces nunca crear constructor en padre sino en el hijo y usar atributos del padre no?

Si la clase es abstracta nunca creas al padre, siempre a los hijos, por lo tanto tener un constructor no tiene mucho sentido, lo que si podes hacer es una funcion protegida en padre que se llame desde el constructor del hijo, pero ya pierde mucho sentido, aunque es valido, los que eran protected ahora son private (o lo mismo a no poner nada).

public abstract class Actor : Monobehaviour
{
	int m_health;
	string m_name;
	
	protected void Init(string name , int health)
	{
		//inicializar
	}
}

public class Player : Actor
{
	public Player(string name, int health)
	{
		Init(name,health);
		//...
	}
}

 

Share this post


Link to post
Share on other sites
hace 12 minutos, lightbug said:

Si la clase es abstracta nunca creas al padre, siempre a los hijos.

Ahh... tienes razón, ya entendi!!, gracias.

Share this post


Link to post
Share on other sites

Buenas @lightbug,

No se a que te refieres con que cuando creas una clase abstracta nunca creas al padre ... pero una clase abstracta es identica a una clase "normal" en todo menos que no podras instanciar un objeto de esa clase.

Pero la clase abstracta puede heredar de una clase padre que no necesariamente tiene porque ser abstracta tambien y la clase abstracta puede tener un constructor como cualquier otra clase con la diferencia de que tendras que llamar a dicho constructor desde los constructores de las clases "hijas".

Buenas @ytinU,

Para lo que comentas de heredar de multiples clases, que como dice @lightbug no es posible en C# (otros lenguajes si lo permiten), yo te recomendaria hacer uso de las interfaces que son una especie de plantillas donde declaras propiedades y metodos que deben tener las clases :

Siguiendo con el ejemplo que utilizabais, yo crearia una interfaz llamada Actor y despues tantas clases como necesites que hereden de la clase MonoBehaviour y utilicen la interfaz Actor ... con eso consigues que el conjunto de clases hereden de la clase MonoBehaviour, que sean independientes unas de las otras pero al mismo tiempo puedas tratar a cualquiera de ellas como Actor.

public interface Actor {
	int health  { get; }
	string name { get; }

	void TakeDamage (int damage);
}

public class Player : MonoBehaviour, Actor {

	[SerializeField] private int _health;
	[SerializeField] private string _name;

	public int health  { get { return this._health; } }
	public string name { get { return this._name; } }

	public void TakeDamage (int damage) { this._health -= damage;
	}
}

public class Enemigo : MonoBehaviour, Actor {

	[SerializeField] private int _health;
	[SerializeField] private string _name;

	public int health  { get { return this._health; } }
	public string name { get { return this._name; } }

	public void TakeDamage (int damage) { this._health -= damage;
	}
}

Con eso tienes las clases Player y Enemigo que seran independientes una de la otra (pueden tener sus propias funciones y atributos), las dos heredaran de la clase MonoBehaviour ... pero en ambos casos podras utilizarlas como si fueran de una "clase ficticia" llamada Actor.

Share this post


Link to post
Share on other sites

Yo lo que todavía no pillo es qué ventajas tiene definir una Interface frente a una clase 'padre', si luego no puedes aprovechar nada del código. No sé si me explico....

Lo que me gustaría conseguir es que, creando una 'plantila' de personaje, luego sólo tuviera que sobreescribir variaciones del mismo método común, pero manteniendo también los originales heredados...

 

En cualquier caso, considero muchísimo más útil (mucho más que las interfaces), el tema de las propiedades, en las que directamente puedes crear algoritmos complejos de gestión, y así ahorrarte tener que definir después su comportamientos, más abajo en el código... Es que el tema de tener que crear métodos para definir un comportamiento o una acción con las propiedades de una clase es un coñazooooo.... XDDD

Share this post


Link to post
Share on other sites

Lo que no entiendo @Arthure es lo de 

int health{get;}

Osea porque crear variables si no van a ser utilizadas?, en las clases que creas

public int health{get{return this._health}}

no soy experto en el tema pero creo que le das la variable de la clase para que ocupe el lugar en la interface, pero porque.. si no la utilizo...

Hola @pioj (vaya ahora no me sale xD) creo que es porque es una plantilla y pues ya sabes que al implementar la interface solo va a ocupar un metodo y los parametros, se limita a crear memoria para eso, lo mismo al crear un script(Start, Update), para aprovechar el código yo lo haria creando una interface base  y en la clase padre construir el razonamiento lógico y en los hijos utilizar ese método.

Share this post


Link to post
Share on other sites

Hola @pioj, tan util son las interfaces como las clases padres ... aunque no se pueden comparar puesto que cada una cubre una necesidad y son cosas muy diferentes (salvo por el hecho de que en ambos casos se utilizan para la herencia, aunque las interfaces no sean herencia propiamente dicha)

La ventaja de definir una interfaz frente a una clase padre, entre otras muchas es que una interfaz no defines funciones ni propiedades, solo las declaras. Puedes hacer jerarquias mucho mas complejas al mismo tiempo que de manera mas sencilla, utilizando interfaces que no mediante clases padres ... y en muchos casos solo podras hacerlo mediante interfaces, por no mencionar que no todos los lenguajes de programacion permite heredar de multiples clases como es el caso de C#. El uso de las interfaces permite un codigo mucho mas facil de leer, facilita el trabajo a la hora de actualizar y lo hace mucho mas escalable.

Hola @ytinU, en las interfaces solo declaras propiedades o metodos que necesiten esten en las clases que contengan esa interfaz ... la propiedad (que no variable) public int health { get; } la he puesto solo porque he cogido como ejemplo el codigo utilizado anteriormente y aparecian tanto health como name, pero esta claro que si no la necesitas pues no hay que ponerla.

Share this post


Link to post
Share on other sites

UnitySpain © Todos los derechos reservados 2020
×
×
  • Create New...