[英]Call method or class using generics
I have a doubt about how generics are implemented and I hope you can support or guide me to implement it in my case.我对 generics 的实现方式有疑问,希望您能支持或指导我在我的情况下实现它。
Well, I'm working on a playlist of files or a gallery and this will be able to play various types of file formats (mp3, jpg, mp4, obj, ect) then I want to avoid modifying my code for each type of method that is responsible for importing these types of files.好吧,我正在处理文件或画廊的播放列表,这将能够播放各种类型的文件格式(mp3、jpg、mp4、obj 等)然后我想避免为每种方法修改我的代码负责导入这些类型的文件。 I have been reading about generics and I see that it solves my problem but I don't know how to implement it.
我一直在阅读有关 generics 的信息,我发现它解决了我的问题,但我不知道如何实现它。
Could you help me with this?你能帮我解决这个问题吗? or is it possible to do what I am trying to do?
还是可以做我想做的事情?
That's all.就这样。 Thank you very much!
非常感谢!
This is my code made in Unity:这是我在 Unity 中制作的代码:
Script 1:脚本 1:
public class GalleryItem : MonoBehaviour
{ #region VARIABLES { #region 变量
[SerializeField]
private GalleryContextMenu contextMenu;
[Header("Settings")]
[SerializeField]
internal Color normalItemColor = Color.white;
[SerializeField]
internal Color hoveredItemColor = new Color32(225, 225, 255, 255);
[SerializeField]
internal Color selectedItemColor = new Color32(0, 175, 255, 255);
[Serializable]
private struct FiletypeIcon
{
public string extension;
public Sprite icon;
}
[Header("Icons")]
[SerializeField]
private FiletypeIcon[] filetypeIcons;
//Listas
private readonly List<int> selectedFileEntries = new List<int>(4);
private readonly List<FileItem> allItems = new List<FileItem>(16);
private readonly List<WidgetItem> allWidgetItems = new List<WidgetItem>();
private List<GameObject> buttonFileList = new List<GameObject>();
internal List<string> allFiles = new List<string>();
//Indice para cada item
internal int sharedValue;
internal string fullFilePath;
//Cantidad de items
private int items;
[Header("Canvas")]
//Contenedor de items
public RectTransform content;
//Item a instanciar
public GameObject itemPrefab;
//Canvas que contiene la galeria de items
public Canvas canvas;
public RectTransform rectTransform;
#endregion
#region MÉTODOS DE INICIALIZACIÓN
private void Awake()
{
items = 0;
}
private void InitializeDataItem()
{
for (int j = 0; j < filetypeIcons.Length; j++)
{
if (fullFilePath.Contains(filetypeIcons[j].extension))
allItems[items].SetFile(filetypeIcons[j].icon, Path.GetFileNameWithoutExtension(fullFilePath));
}
}
#endregion
#region MÉTODOS PARA ABRIR EL EXPLORADOR DE ARCHIVOS
public void StartFileBrowser()
{
StartCoroutine(ShowLoadingCoroutine());
}
IEnumerator ShowLoadingCoroutine()
{
yield return FileBrowser.WaitForLoadDialog(FileBrowser.PickMode.FilesAndFolders, true, null, null, "Abrir archivos y carpetas", "Cargar");
if (FileBrowser.Success)
{
fullFilePath = FileBrowser.Result[0].ToLowerInvariant();
OnCreateItem("item", itemPrefab, content);
OnCreateWidgetItem("WidgetButton");
}
}
#endregion
#region MÉTODO PARA AGREGAR Y ELEIMINAR ELEMENTOS DE LA GALERÍA
public void DeleteItem()
{
Destroy(buttonFileList[sharedValue]);
Destroy(allItems[sharedValue]);
buttonFileList.RemoveAt(sharedValue);
allItems.RemoveAt(sharedValue);
allWidgetItems.RemoveAt(sharedValue);
allFiles.RemoveAt(sharedValue);
items -= 1;
Refresh();
}
private void Refresh()
{
for (int i = 0; i < buttonFileList.Count; i++)
buttonFileList[i].name = "item_" + i;
for (int i = 0; i < allWidgetItems.Count; i++)
{
allWidgetItems[i].gameObject.name = "WidgetButton" + i;
}
if (buttonFileList.Count == 0)
items = 0;
}
private void OnCreateWidgetItem(string name)
{
WidgetItem widget = GameObject.Find("WidgetButton").GetComponentInChildren<WidgetItem>();
widget.name = name + "_" + (items - 1);
allWidgetItems.Add(widget);
}
private void OnCreateItem(string name, GameObject prefab, Transform parent)
{
FileItem item = (FileItem)Instantiate(prefab.GetComponent<FileItem>(), parent, false);
item.name = name + "_" + items;
buttonFileList.Add(item.gameObject);
allItems.Add(item);
allFiles.Add(fullFilePath);
InitializeDataItem();
items += 1;
}
#endregion
#region MENÚ CONTEXTUAL
internal void OnContextMenuTriggered()
{
Vector2 position;
RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, Input.mousePosition, canvas.worldCamera, out position);
contextMenu.Show(position, false);
}
#endregion
#region HOVER PARA ELEMENTOS
public void OnItemSelected(FileItem item, bool isDobleClick)
{
if (item == null)
return;
if (!isDobleClick)
{
selectedFileEntries.Clear();
selectedFileEntries.Add(item.Position);
}
for (int i = 0; i < allItems.Count; i++)
{
if (allItems[i].gameObject.activeSelf)
allItems[i].SetSelected(false);
}
item.SetSelected(selectedFileEntries.Contains(item.Position));
}
public void OnSelectedWidgetItem()
{
for (int i = 0; i < allWidgetItems.Count; i++)
{
allWidgetItems[i].isPlaying = false;
allWidgetItems[i].PlayingNull();
}
}
Script 2:脚本 2:
public class GalleryItem : MonoBehaviour
{ #region VARIABLES { #region 变量
[SerializeField]
private GalleryContextMenu contextMenu;
[Header("Settings")]
[SerializeField]
internal Color normalItemColor = Color.white;
[SerializeField]
internal Color hoveredItemColor = new Color32(225, 225, 255, 255);
[SerializeField]
internal Color selectedItemColor = new Color32(0, 175, 255, 255);
[Serializable]
private struct FiletypeIcon
{
public string extension;
public Sprite icon;
}
[Header("Icons")]
[SerializeField]
private FiletypeIcon[] filetypeIcons;
//Listas
private readonly List<int> selectedFileEntries = new List<int>(4);
private readonly List<FileItem> allItems = new List<FileItem>(16);
private readonly List<WidgetItem> allWidgetItems = new List<WidgetItem>();
private List<GameObject> buttonFileList = new List<GameObject>();
internal List<string> allFiles = new List<string>();
//Indice para cada item
internal int sharedValue;
internal string fullFilePath;
//Cantidad de items
private int items;
[Header("Canvas")]
//Contenedor de items
public RectTransform content;
//Item a instanciar
public GameObject itemPrefab;
//Canvas que contiene la galeria de items
public Canvas canvas;
public RectTransform rectTransform;
#endregion
#region MÉTODOS DE INICIALIZACIÓN
private void Awake()
{
items = 0;
}
private void InitializeDataItem()
{
for (int j = 0; j < filetypeIcons.Length; j++)
{
if (fullFilePath.Contains(filetypeIcons[j].extension))
allItems[items].SetFile(filetypeIcons[j].icon, Path.GetFileNameWithoutExtension(fullFilePath));
}
}
#endregion
#region MÉTODOS PARA ABRIR EL EXPLORADOR DE ARCHIVOS
public void StartFileBrowser()
{
StartCoroutine(ShowLoadingCoroutine());
}
IEnumerator ShowLoadingCoroutine()
{
yield return FileBrowser.WaitForLoadDialog(FileBrowser.PickMode.FilesAndFolders, true, null, null, "Abrir archivos y carpetas", "Cargar");
if (FileBrowser.Success)
{
fullFilePath = FileBrowser.Result[0].ToLowerInvariant();
OnCreateItem("item", itemPrefab, content);
OnCreateWidgetItem("WidgetButton");
}
}
#endregion
#region MÉTODO PARA AGREGAR Y ELEIMINAR ELEMENTOS DE LA GALERÍA
public void DeleteItem()
{
Destroy(buttonFileList[sharedValue]);
Destroy(allItems[sharedValue]);
buttonFileList.RemoveAt(sharedValue);
allItems.RemoveAt(sharedValue);
allWidgetItems.RemoveAt(sharedValue);
allFiles.RemoveAt(sharedValue);
items -= 1;
Refresh();
}
private void Refresh()
{
for (int i = 0; i < buttonFileList.Count; i++)
buttonFileList[i].name = "item_" + i;
for (int i = 0; i < allWidgetItems.Count; i++)
{
allWidgetItems[i].gameObject.name = "WidgetButton" + i;
}
if (buttonFileList.Count == 0)
items = 0;
}
private void OnCreateWidgetItem(string name)
{
WidgetItem widget = GameObject.Find("WidgetButton").GetComponentInChildren<WidgetItem>();
widget.name = name + "_" + (items - 1);
allWidgetItems.Add(widget);
}
private void OnCreateItem(string name, GameObject prefab, Transform parent)
{
FileItem item = (FileItem)Instantiate(prefab.GetComponent<FileItem>(), parent, false);
item.name = name + "_" + items;
buttonFileList.Add(item.gameObject);
allItems.Add(item);
allFiles.Add(fullFilePath);
InitializeDataItem();
items += 1;
}
#endregion
#region MENÚ CONTEXTUAL
internal void OnContextMenuTriggered()
{
Vector2 position;
RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, Input.mousePosition, canvas.worldCamera, out position);
contextMenu.Show(position, false);
}
#endregion
#region HOVER PARA ELEMENTOS
public void OnItemSelected(FileItem item, bool isDobleClick)
{
if (item == null)
return;
if (!isDobleClick)
{
selectedFileEntries.Clear();
selectedFileEntries.Add(item.Position);
}
for (int i = 0; i < allItems.Count; i++)
{
if (allItems[i].gameObject.activeSelf)
allItems[i].SetSelected(false);
}
item.SetSelected(selectedFileEntries.Contains(item.Position));
}
public void OnSelectedWidgetItem()
{
for (int i = 0; i < allWidgetItems.Count; i++)
{
allWidgetItems[i].isPlaying = false;
allWidgetItems[i].PlayingNull();
}
}
Generics are useful in a situation where you want a way of taking some description of an operation and applying it to a bunch of different types. Generics 在您想要一种对操作进行一些描述并将其应用于一堆不同类型的情况下很有用。 For instance, you might want to make a container that can hold different types of objects.
例如,您可能想要制作一个可以容纳不同类型对象的容器。
In the case of a playlist that's not really what you're doing, because you're thinking about a list of objects of differing types.在播放列表的情况下,这并不是您真正在做的事情,因为您正在考虑不同类型的对象列表。 What you want instead is a base type or interface that provides the functionality you need, like so:
相反,您想要的是提供所需功能的基本类型或接口,如下所示:
interface IPlayable
{
void play();
void stop();
void rewind();
// ...
}
class MP3File : IPlayable
{
public void play() { /* ... */ }
// ...
}
class MP3File : IPlayable
{
public void play() { /* ... */ }
// ...
}
class WAVFile : IPlayable
{
public void play() { /* ... */ }
// ...
}
and then you could declare your playlist as然后你可以将你的播放列表声明为
System.Collections.Generic.List<IPlayable> myPlaylist;
and do things like并做类似的事情
myPlaylist.add(new MP3File("song.mp3"));
myPlaylist[i].play();
You mentioned wanting to load things.你提到想要加载东西。 For that what you probably want is a factory method, like so
为此,您可能想要的是工厂方法,就像这样
IPlayable makePlayable(string filename)
{
switch(Path.getExtension(filename))
{
case ".mp3" : return new MP3File(filename);
case ".wav" : return new WaveFile(filename);
// ...
default: return null; // or throw, or ...
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.